Compare commits
103 Commits
citadel
...
wip/carlos
Author | SHA1 | Date | |
---|---|---|---|
![]() |
208e292df1 | ||
![]() |
548e5138fc | ||
![]() |
6b8d95d9c4 | ||
![]() |
faec8d29b0 | ||
![]() |
4b88a769d2 | ||
![]() |
6704e986a0 | ||
![]() |
d55b44df50 | ||
![]() |
6496cd7c55 | ||
![]() |
6f3ce4de24 | ||
![]() |
034aff4306 | ||
![]() |
af5f93377a | ||
![]() |
abd858fb69 | ||
![]() |
09e02a772e | ||
![]() |
c850aa9733 | ||
![]() |
5a1c7e4a54 | ||
![]() |
e324f0fad0 | ||
![]() |
5978531963 | ||
![]() |
bc111bf958 | ||
![]() |
074d78bd9b | ||
![]() |
2e604709df | ||
![]() |
6c265c131f | ||
![]() |
06adde5c6b | ||
![]() |
a2616d83e8 | ||
![]() |
92bc79fd51 | ||
![]() |
ef67fab737 | ||
![]() |
9acb7f0eed | ||
![]() |
c678cdab5a | ||
![]() |
91f6b3b5bc | ||
![]() |
696915a951 | ||
![]() |
2e07c55241 | ||
![]() |
0f0848191e | ||
![]() |
4b0d3f44e1 | ||
![]() |
4f794d3acb | ||
![]() |
3252ef5dd7 | ||
![]() |
0c9bbbe90e | ||
![]() |
bb62d9e4b0 | ||
![]() |
579220a762 | ||
![]() |
575a4ca281 | ||
![]() |
4b7f2905d6 | ||
![]() |
c7758046eb | ||
![]() |
e64112de64 | ||
![]() |
05f385c8ee | ||
![]() |
8a2b529ca3 | ||
![]() |
0c92417178 | ||
![]() |
543d232b51 | ||
![]() |
4398d63566 | ||
![]() |
dc022a67b0 | ||
![]() |
60fa895ae3 | ||
![]() |
7bb3fe25aa | ||
![]() |
6c5bba94fd | ||
![]() |
667b2726f5 | ||
![]() |
1d3588ba48 | ||
![]() |
16317cec12 | ||
![]() |
f3991c0164 | ||
![]() |
b07d9c5f92 | ||
![]() |
be51a8c18c | ||
![]() |
11c86f9cb3 | ||
![]() |
87c0821a30 | ||
![]() |
03f2bade19 | ||
![]() |
a3825f2085 | ||
![]() |
8b2a89041a | ||
![]() |
52da5fe4f2 | ||
![]() |
307be1e495 | ||
![]() |
9b3ca86b7c | ||
![]() |
da55f15156 | ||
![]() |
b13fe4895f | ||
![]() |
aae4a6065c | ||
![]() |
1555ecad11 | ||
![]() |
292b4dd605 | ||
![]() |
4766e2f858 | ||
![]() |
e3fe8c3dd1 | ||
![]() |
d3e1ce7dbc | ||
![]() |
63ad2c958d | ||
![]() |
849cc3d7f5 | ||
![]() |
8d8c933eb4 | ||
![]() |
2363f4c30b | ||
![]() |
5d45722362 | ||
![]() |
cef6520836 | ||
![]() |
0fbbeb0c82 | ||
![]() |
b97519bb6e | ||
![]() |
60b3f628a6 | ||
![]() |
37deba9557 | ||
![]() |
89cefd037f | ||
![]() |
c9efadacd1 | ||
![]() |
df724f5c75 | ||
![]() |
44bb21c7aa | ||
![]() |
73e705a49b | ||
![]() |
2316dfe394 | ||
![]() |
9597b5a703 | ||
![]() |
0be0a14225 | ||
![]() |
7fafec21b6 | ||
![]() |
88f03d3a26 | ||
![]() |
edc399e5cf | ||
![]() |
908a331fa8 | ||
![]() |
3083e98254 | ||
![]() |
7dc1a28c8c | ||
![]() |
3ce5b34ade | ||
![]() |
5677fbb64d | ||
![]() |
e7f29e764f | ||
![]() |
5563bfe7d9 | ||
![]() |
cd00e69ce3 | ||
![]() |
fe1d297680 | ||
![]() |
67a31633d8 |
375
.gitlab-ci.yml
375
.gitlab-ci.yml
@ -1,372 +1,117 @@
|
||||
include:
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/fedora.yml'
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/ci-fairy.yml'
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
|
||||
stages:
|
||||
- review
|
||||
- prepare
|
||||
- code-review
|
||||
- build
|
||||
- test
|
||||
- analyze
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
FDO_UPSTREAM_REPO: GNOME/mutter
|
||||
|
||||
.mutter.fedora:34@common:
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 34
|
||||
BASE_TAG: '2021-09-04.1'
|
||||
FDO_DISTRIBUTION_PACKAGES:
|
||||
asciidoc
|
||||
clang
|
||||
gcovr
|
||||
gdm
|
||||
gnome-shell
|
||||
python3-dbusmock
|
||||
sassc
|
||||
uncrustify
|
||||
xorg-x11-server-Xvfb
|
||||
|
||||
FDO_DISTRIBUTION_EXEC: |
|
||||
dnf install -y 'dnf-command(builddep)' &&
|
||||
|
||||
dnf builddep -y mutter --setopt=install_weak_deps=False &&
|
||||
dnf builddep -y gnome-shell --setopt=install_weak_deps=False &&
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/glib.git \
|
||||
main . 02742ef957b532789c003eef80ec7f51c370e3d5 &&
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas.git \
|
||||
41.alpha . &&
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/gjs.git \
|
||||
1.69.2 . &&
|
||||
|
||||
rpm -e --nodeps gnome-bluetooth-libs-devel \
|
||||
mutter mutter-devel \
|
||||
gnome-shell &&
|
||||
|
||||
dnf clean all
|
||||
|
||||
default:
|
||||
# Cancel jobs if newer commits are pushed to the branch
|
||||
interruptible: true
|
||||
# Auto-retry jobs in case of infra failures
|
||||
retry:
|
||||
max: 1
|
||||
when:
|
||||
- 'runner_system_failure'
|
||||
- 'stuck_or_timeout_failure'
|
||||
- 'scheduler_failure'
|
||||
- 'api_failure'
|
||||
|
||||
.mutter.fedora:34@x86_64:
|
||||
extends: .mutter.fedora:34@common
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "x86_64-${BASE_TAG}"
|
||||
|
||||
.mutter.fedora:34@aarch64:
|
||||
extends: .mutter.fedora:34@common
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "aarch64-${BASE_TAG}"
|
||||
tags:
|
||||
- aarch64
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_MERGE_REQUEST_IID'
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
|
||||
.pipline-guard: &pipline-guard
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
- if: '$CI_COMMIT_BRANCH =~ /^gnome-[0-9-]+$/'
|
||||
- when: 'manual'
|
||||
- coverage
|
||||
|
||||
check-commit-log:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: review
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
script:
|
||||
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
|
||||
then
|
||||
ci-fairy check-commits --junit-xml=commit-message-junit-report.xml ;
|
||||
else
|
||||
echo "Not a merge request" ;
|
||||
fi
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- commit-message-junit-report.xml
|
||||
reports:
|
||||
junit: commit-message-junit-report.xml
|
||||
<<: *pipline-guard
|
||||
- ./.gitlab-ci/check-commit-log.sh
|
||||
only:
|
||||
- merge_requests
|
||||
|
||||
check-merge-request:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: review
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
|
||||
then
|
||||
ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request-report.xml ;
|
||||
else
|
||||
echo "Not a merge request" ;
|
||||
fi
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- check-merge-request-report.xml
|
||||
reports:
|
||||
junit: check-merge-request-report.xml
|
||||
<<: *pipline-guard
|
||||
|
||||
build-fedora-container@x86_64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@x86_64
|
||||
- .mutter.fedora:34@x86_64
|
||||
stage: prepare
|
||||
needs:
|
||||
- check-commit-log
|
||||
- check-merge-request
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
|
||||
build-fedora-container@aarch64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@aarch64
|
||||
- .mutter.fedora:34@aarch64
|
||||
stage: prepare
|
||||
needs:
|
||||
- check-commit-log
|
||||
- check-merge-request
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
|
||||
check-code-style:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
stage: code-review
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
script:
|
||||
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
|
||||
then
|
||||
git remote add target $CI_MERGE_REQUEST_PROJECT_URL.git ;
|
||||
git fetch target $CI_MERGE_REQUEST_TARGET_BRANCH_NAME ;
|
||||
export common_parent_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "target/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME") <(git rev-list --first-parent HEAD) | head -1) ;
|
||||
python3 -u ./check-style.py --dry-run --sha $common_parent_sha ;
|
||||
else
|
||||
echo "Not a merge request" ;
|
||||
fi
|
||||
allow_failure: true
|
||||
|
||||
.build-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
build-mutter:
|
||||
stage: build
|
||||
needs: []
|
||||
script:
|
||||
- meson . build -Dbuildtype=debugoptimized -Db_coverage=true -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
|
||||
- meson compile -C build
|
||||
- meson install -C build
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- build
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
build-mutter@x86_64:
|
||||
extends:
|
||||
- .build-mutter
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
|
||||
build-mutter@aarch64:
|
||||
extends:
|
||||
- .build-mutter
|
||||
- .mutter.fedora:34@aarch64
|
||||
needs:
|
||||
- build-fedora-container@aarch64
|
||||
|
||||
build-without-opengl-and-glx@x86_64:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
build-without-opengl-and-glx:
|
||||
stage: build
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
needs: []
|
||||
script:
|
||||
- meson . build -Dbuildtype=debugoptimized -Dopengl=false -Dglx=false -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
|
||||
- meson compile -C build
|
||||
- meson install -C build
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
build-without-native-backend-and-wayland@x86_64:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
build-without-native-backend-and-wayland:
|
||||
stage: build
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
needs: []
|
||||
script:
|
||||
- meson . build -Dbuildtype=debugoptimized -Dnative_backend=false -Dudev=false -Dwayland=false -Dcore_tests=false -Dnative_tests=false --werror --prefix /usr
|
||||
- meson compile -C build
|
||||
- meson install -C build
|
||||
- meson . build -Dbuildtype=debugoptimized -Dnative_backend=false -Dudev=false -Dwayland=false -Dcore_tests=false --werror --prefix /usr
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
.test-setup: &test-setup
|
||||
test-mutter:
|
||||
stage: test
|
||||
dependencies:
|
||||
- build-mutter
|
||||
needs: ["build-mutter"]
|
||||
variables:
|
||||
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
|
||||
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
|
||||
MUTTER_DEBUG_DUMMY_MODE_SPECS: "800x600@10.0"
|
||||
PIPEWIRE_DEBUG: 2
|
||||
PIPEWIRE_LOG: "$CI_PROJECT_DIR/build/meson-logs/pipewire.log"
|
||||
XVFB_SERVER_ARGS: "+iglx -noreset"
|
||||
G_SLICE: "always-malloc"
|
||||
MALLOC_CHECK_: "3"
|
||||
NO_AT_BRIDGE: "1"
|
||||
before_script:
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
# Disable e.g. audio support to not dead lock screen cast tests
|
||||
- rm -f /usr/share/pipewire/media-session.d/with-*
|
||||
- mkdir -m 700 $XDG_RUNTIME_DIR
|
||||
- pipewire & sleep 2
|
||||
|
||||
.test-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
<<: *test-setup
|
||||
stage: test
|
||||
script:
|
||||
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS"
|
||||
catchsegv meson test -C build --no-rebuild -t 10
|
||||
- dconf update
|
||||
- mkdir -m 700 $XDG_RUNTIME_DIR
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
- >
|
||||
dbus-run-session -- xvfb-run -s '+iglx -noreset'
|
||||
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
reports:
|
||||
junit: "build/meson-logs/testlog-catchsegv.junit.xml"
|
||||
name: "mutter-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
test-mutter@x86_64:
|
||||
extends:
|
||||
- .test-mutter
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
|
||||
test-mutter@aarch64:
|
||||
extends:
|
||||
- .test-mutter
|
||||
- .mutter.fedora:34@aarch64
|
||||
needs:
|
||||
- build-mutter@aarch64
|
||||
|
||||
.test-mutter-coverage:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
stage: analyze
|
||||
test-mutter-coverage:
|
||||
stage: coverage
|
||||
dependencies:
|
||||
- test-mutter
|
||||
needs: ["test-mutter"]
|
||||
script:
|
||||
- ninja -C build coverage
|
||||
- cat build/meson-logs/coverage.txt
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs/coveragereport
|
||||
coverage: '/^TOTAL.*\s+(\d+\%)$/'
|
||||
- build/meson-logs
|
||||
when: manual
|
||||
except:
|
||||
refs:
|
||||
- tags
|
||||
- master
|
||||
|
||||
test-mutter-coverage@x86_64:
|
||||
extends:
|
||||
- .test-mutter-coverage
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- test-mutter@x86_64
|
||||
|
||||
test-mutter-coverage@aarch64:
|
||||
extends:
|
||||
- .test-mutter-coverage
|
||||
- .mutter.fedora:34@aarch64
|
||||
needs:
|
||||
- test-mutter@aarch64
|
||||
|
||||
can-build-gnome-shell@x86_64:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
can-build-gnome-shell:
|
||||
stage: test
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
dependencies:
|
||||
- build-mutter
|
||||
needs: ["build-mutter"]
|
||||
before_script:
|
||||
- meson install --no-rebuild -C build
|
||||
script:
|
||||
- .gitlab-ci/checkout-gnome-shell.sh
|
||||
- meson gnome-shell gnome-shell/build --prefix /usr -Dman=false
|
||||
- meson install -C gnome-shell/build
|
||||
|
||||
test-mutter-coverity:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule" && $MUTTER_SCHEDULED_JOB == "coverity"'
|
||||
when: always
|
||||
- when: manual
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
stage: analyze
|
||||
allow_failure: true
|
||||
script:
|
||||
- .gitlab-ci/download-coverity-tarball.sh
|
||||
- CC=clang meson coverity-build -Dprofiler=false
|
||||
- ./coverity/cov-analysis-linux64-*/bin/cov-build --dir cov-int meson compile -C coverity-build
|
||||
- tar czf cov-int.tar.gz cov-int
|
||||
- curl https://scan.coverity.com/builds?project=mutter
|
||||
--form token=$COVERITY_TOKEN --form email=carlosg@gnome.org
|
||||
--form file=@cov-int.tar.gz --form version="`git describe --tags`"
|
||||
--form description="GitLab CI build"
|
||||
cache:
|
||||
key: coverity-tarball
|
||||
paths:
|
||||
- coverity
|
||||
|
||||
dist-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
<<: *test-setup
|
||||
stage: deploy
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
script:
|
||||
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS" meson dist -C build
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
changes:
|
||||
- "**/meson.build"
|
||||
- meson/*
|
||||
|
||||
dist-mutter-tarball:
|
||||
extends: dist-mutter
|
||||
artifacts:
|
||||
expose_as: 'Get tarball here'
|
||||
paths:
|
||||
- build/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
- ninja -C gnome-shell/build install
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
28
.gitlab-ci/Dockerfile
Normal file
28
.gitlab-ci/Dockerfile
Normal file
@ -0,0 +1,28 @@
|
||||
# Rebuild and push with
|
||||
#
|
||||
# cd .gitlab-ci/
|
||||
# podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v4 .
|
||||
# podman push registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
#
|
||||
|
||||
FROM fedora:32
|
||||
|
||||
RUN dnf -y update && dnf -y upgrade && \
|
||||
dnf install -y 'dnf-command(builddep)' && \
|
||||
dnf install -y 'dnf-command(copr)' && \
|
||||
dnf copr enable -y jadahl/mutter-ci && \
|
||||
|
||||
dnf builddep -y mutter --setopt=install_weak_deps=False && \
|
||||
|
||||
# For running unit tests
|
||||
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 \
|
||||
'*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center gcovr \
|
||||
libnma python3-gobject python3-dbusmock \
|
||||
--setopt=install_weak_deps=False && \
|
||||
|
||||
# GNOME Shell
|
||||
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
|
||||
dnf remove -y gnome-bluetooth-libs-devel && \
|
||||
dnf remove -y --noautoremove mutter mutter-devel && \
|
||||
|
||||
dnf clean all
|
60
.gitlab-ci/check-commit-log.sh
Executable file
60
.gitlab-ci/check-commit-log.sh
Executable file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
echo Cannot review non-merge request
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
|
||||
branch_point=$(git merge-base HEAD FETCH_HEAD)
|
||||
|
||||
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
|
||||
|
||||
if [ -z "$commits" ]; then
|
||||
echo Commit range empty
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function commit_message_has_url() {
|
||||
commit=$1
|
||||
commit_message=$(git show -s --format='format:%b' $commit)
|
||||
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(-/\)\?\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
|
||||
return $?
|
||||
}
|
||||
|
||||
function commit_message_subject_is_compliant() {
|
||||
commit=$1
|
||||
commit_message_subject=$(git show -s --format='format:%s' $commit)
|
||||
|
||||
if echo "$commit_message_subject" | grep -qe "\(^meta-\|^Meta\)"; then
|
||||
echo " - message subject should not be prefixed with 'meta-' or 'Meta'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if echo "$commit_message_subject" | grep -qe "\.[ch]:"; then
|
||||
echo " - message subject prefix should not include .c, .h, etc."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
RET=0
|
||||
for commit in $commits; do
|
||||
commit_short=$(echo $commit | cut -c -8)
|
||||
|
||||
if ! commit_message_has_url $commit; then
|
||||
echo "Commit $commit_short needs a merge request or issue URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
errors=$(commit_message_subject_is_compliant $commit)
|
||||
if [ $? != 0 ]; then
|
||||
echo "Commit message for $commit_short is not compliant:"
|
||||
echo "$errors"
|
||||
RET=1
|
||||
fi
|
||||
done
|
||||
|
||||
exit $RET
|
@ -1,19 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
fetch() {
|
||||
local remote=$1
|
||||
local ref=$2
|
||||
|
||||
git fetch --quiet --depth=1 $remote $ref 2>/dev/null
|
||||
}
|
||||
|
||||
gnome_shell_target=
|
||||
|
||||
echo -n Cloning into gnome-shell ...
|
||||
if git clone --quiet --depth=1 https://gitlab.gnome.org/GNOME/gnome-shell.git; then
|
||||
echo \ done
|
||||
else
|
||||
echo \ failed
|
||||
git clone https://gitlab.gnome.org/GNOME/gnome-shell.git
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo Checkout failed
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -23,33 +15,19 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//mutter/gnome-shell}
|
||||
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
||||
|
||||
echo -n Looking for $merge_request_branch on remote ...
|
||||
if fetch $merge_request_remote $merge_request_branch; then
|
||||
echo \ found
|
||||
echo Looking for $merge_request_branch on remote ...
|
||||
if git fetch -q $merge_request_remote $merge_request_branch 2>/dev/null; then
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
|
||||
echo -n Looking for $CI_MERGE_REQUEST_TARGET_BRANCH_NAME instead ...
|
||||
if fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME; then
|
||||
echo \ found
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$gnome_shell_target" ]; then
|
||||
echo -n Looking for $CI_COMMIT_REF_NAME on remote ...
|
||||
if fetch origin $CI_COMMIT_REF_NAME; then
|
||||
echo \ found
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
gnome_shell_target=HEAD
|
||||
gnome_shell_target=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
echo Using $gnome_shell_target instead
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$gnome_shell_target" ]; then
|
||||
gnome_shell_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
|
||||
gnome_shell_target=${gnome_shell_target:-origin/master}
|
||||
echo Using $gnome_shell_target instead
|
||||
fi
|
||||
|
||||
git checkout -q $gnome_shell_target
|
||||
|
@ -1,19 +0,0 @@
|
||||
patterns:
|
||||
deny:
|
||||
- regex: '^$CI_MERGE_REQUEST_PROJECT_URL/(-/)?merge_requests/$CI_MERGE_REQUEST_IID$'
|
||||
message: Commit message must not contain a link to its own merge request
|
||||
- regex: '^(meta-|Meta)'
|
||||
message: Commit message subject should not be prefixed with 'meta-' or 'Meta'
|
||||
where: subject
|
||||
- regex: '^(clutter-|Clutter)'
|
||||
message: Commit message subject should not be prefixed with 'clutter-' or 'Clutter', use 'clutter/' instead
|
||||
where: subject
|
||||
- regex: '^(cogl-|Cogl)'
|
||||
message: Commit message subject should not be prefixed with 'cogl-' or 'Cogl', use 'cogl/' instead
|
||||
where: subject
|
||||
- regex: '^[^:]+: [a-z]'
|
||||
message: "Commit message subject should be properly Capitalized. E.g. 'window: Marginalize extradicity'"
|
||||
where: subject
|
||||
- regex: '^\S*\.[ch]:'
|
||||
message: Commit message subject prefix should not include .c, .h, etc.
|
||||
where: subject
|
@ -1,38 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# We need a coverity token to fetch the tarball
|
||||
if [ -x $COVERITY_TOKEN ]
|
||||
then
|
||||
echo "No coverity token. Run this job from a protected branch."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
mkdir -p coverity
|
||||
|
||||
# Download and check MD5 first
|
||||
curl https://scan.coverity.com/download/linux64 \
|
||||
--data "token=$COVERITY_TOKEN&project=mutter&md5=1" \
|
||||
--output /tmp/coverity_tool.md5
|
||||
|
||||
diff /tmp/coverity_tool.md5 coverity/coverity_tool.md5 >/dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 -a -d coverity/cov-analysis* ]
|
||||
then
|
||||
echo "Coverity tarball is up-to-date"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Download and extract coverity tarball
|
||||
curl https://scan.coverity.com/download/linux64 \
|
||||
--data "token=$COVERITY_TOKEN&project=mutter" \
|
||||
--output /tmp/coverity_tool.tgz
|
||||
|
||||
rm -rf ./coverity/cov-analysis*
|
||||
|
||||
tar zxf /tmp/coverity_tool.tgz -C coverity/
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
mv /tmp/coverity_tool.md5 coverity/
|
||||
fi
|
||||
|
||||
rm /tmp/coverity_tool.tgz
|
@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $# -lt 3 ]]; then
|
||||
echo Usage: $0 [options] [repo-url] [commit] [subdir]
|
||||
echo Options:
|
||||
echo -Dkey=val
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MESON_OPTIONS=()
|
||||
|
||||
while [[ $1 =~ ^-D ]]; do
|
||||
MESON_OPTIONS+=( "$1" )
|
||||
shift
|
||||
done
|
||||
|
||||
REPO_URL="$1"
|
||||
TAG_OR_BRANCH="$2"
|
||||
SUBDIR="$3"
|
||||
COMMIT="$4"
|
||||
|
||||
REPO_DIR="$(basename ${REPO_URL%.git})"
|
||||
|
||||
git clone --depth 1 "$REPO_URL" -b "$TAG_OR_BRANCH"
|
||||
pushd "$REPO_DIR"
|
||||
pushd "$SUBDIR"
|
||||
|
||||
if [ ! -z "$COMMIT" ]; then
|
||||
git fetch origin "$COMMIT"
|
||||
git checkout "$COMMIT"
|
||||
fi
|
||||
|
||||
meson --prefix=/usr _build "${MESON_OPTIONS[@]}"
|
||||
meson install -C _build
|
||||
popd
|
||||
popd
|
||||
rm -rf "$REPO_DIR"
|
286
HACKING.md
286
HACKING.md
@ -1,286 +0,0 @@
|
||||
# Style
|
||||
|
||||
The coding style used is primarily the GNU flavor of the [GNOME coding
|
||||
style][gnome-coding-style], with some additions described below.
|
||||
|
||||
## General
|
||||
|
||||
* Use this code style on new code. When changing old code with a different
|
||||
code style, feel free to also adjust it to use this code style.
|
||||
|
||||
* Use regular C types and `stdint.h` types instead of GLib fundamental
|
||||
types, except for `gboolean`, and `guint`/`gulong` for GSource IDs and
|
||||
signal handler IDs. That means e.g. `uint64_t` instead of `guint64`, `int`
|
||||
instead of `gint`, `unsigned int` instead of `guint` if unsignedness
|
||||
is of importance, `uint8_t` instead of `guchar`, and so on.
|
||||
|
||||
* Try to to limit line length to 80 characters, although it's not a
|
||||
strict limit.
|
||||
|
||||
* Usage of `g_autofree` and `g_autoptr` is encouraged. The style to use is
|
||||
|
||||
```c
|
||||
g_autofree char *text = NULL;
|
||||
g_autoptr (MetaSomeThing) thing = NULL;
|
||||
|
||||
text = g_strdup_printf ("The text: %d", a_number);
|
||||
thing = g_object_new (META_TYPE_SOME_THING,
|
||||
"text", text,
|
||||
NULL);
|
||||
thinger_use_thing (rocket, thing);
|
||||
```
|
||||
|
||||
* Declare variables at the top of the block they are used, but avoid
|
||||
non-trivial logic among variable declarations. Non-trivial logic can be
|
||||
getting a pointer that may be `NULL`, any kind of math, or anything
|
||||
that may have side effects.
|
||||
|
||||
* Instead of boolean arguments in functions, prefer enums or flags when
|
||||
they're more expressive. The naming convention for flags is
|
||||
|
||||
```c
|
||||
typedef _MetaSomeThingFlags
|
||||
{
|
||||
META_SOME_THING_FLAG_NONE = 0,
|
||||
META_SOME_THING_FLAG_ALTER_REALITY = 1 << 0,
|
||||
META_SOME_THING_FLAG_MANIPULATE_PERCEPTION = 1 << 1,
|
||||
} MetaSomeThingFlags;
|
||||
```
|
||||
|
||||
* Use `g_new0 ()` etc. instead of `g_slice_new0 ()`.
|
||||
|
||||
* Initialize and assign floating point variables (i.e. `float` or
|
||||
`double`) using the form `floating_point = 3.14159` or `ratio = 2.0`.
|
||||
|
||||
## Header (.h) files
|
||||
|
||||
* The return type and `*` are separated by a space.
|
||||
* Function name starts one space after the last `*`.
|
||||
* Parenthesis comes one space after the function name.
|
||||
|
||||
As an example, this is how functions in a header file should look like:
|
||||
|
||||
```c
|
||||
gboolean meta_udev_is_drm_device (MetaUdev *udev,
|
||||
GUdevDevice *device);
|
||||
|
||||
GList * meta_udev_list_drm_devices (MetaUdev *udev,
|
||||
GError **error);
|
||||
|
||||
MetaUdev * meta_udev_new (MetaBackendNative *backend_native);
|
||||
```
|
||||
|
||||
## Source code
|
||||
|
||||
Keep functions in the following order in source files:
|
||||
|
||||
1. GPL header
|
||||
2. Enums
|
||||
3. Structures
|
||||
4. Function prototypes
|
||||
5. `G_DEFINE_TYPE()`
|
||||
6. Static variables
|
||||
7. Auxiliary functions
|
||||
8. Callbacks
|
||||
9. Interface implementations
|
||||
10. Parent vfunc overrides
|
||||
11. class_init and init
|
||||
12. Public API
|
||||
|
||||
### Structures
|
||||
|
||||
Each structure field has a space after their type name. Structure fields aren't
|
||||
aligned. For example:
|
||||
|
||||
```c
|
||||
struct _MetaFooBar
|
||||
{
|
||||
MetaFoo parent;
|
||||
|
||||
MetaBar *bar;
|
||||
MetaSomething *something;
|
||||
};
|
||||
```
|
||||
|
||||
### Function Prototypes
|
||||
|
||||
Function prototypes must be formatted just like in header files.
|
||||
|
||||
### Overrides
|
||||
|
||||
When overriding parent class vfuncs, or implementing an interface, vfunc
|
||||
overrides should be named as a composition of the current class prefix,
|
||||
followed by the vfunc name. For example:
|
||||
|
||||
|
||||
```c
|
||||
static void
|
||||
meta_bar_spawn_unicorn (MetaParent *parent)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_bar_dispose (GObject *object)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_bar_finalize (GObject *object)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_bar_class_init (MetaBarClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaParentClass *parent_class = META_PARENT_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_bar_dispose;
|
||||
object_class->finalize = meta_bar_finalize;
|
||||
|
||||
parent_class->spawn_unicorn = meta_bar_spawn_unicorn;
|
||||
}
|
||||
```
|
||||
|
||||
### Interface Implementations
|
||||
|
||||
When implementing interfaces, two groups of functions are involved: the init
|
||||
function, and the overrides.
|
||||
|
||||
The interface init function is named after the interface type in snake case,
|
||||
followed by the `_iface_init` suffix. For example:
|
||||
|
||||
|
||||
```c
|
||||
static void meta_foo_iface_init (MetaFooInterface *foo_iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaBar, meta_bar, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_FOO,
|
||||
meta_foo_iface_init));
|
||||
```
|
||||
|
||||
Then, when implementing each vfunc of the interface, follow the same pattern
|
||||
of the [Overrides](###Overrides) section. Here's an example:
|
||||
|
||||
```c
|
||||
static void
|
||||
meta_bar_do_something (MetaFoo *foo)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_foo_iface_init (MetaFooInterface *foo_iface)
|
||||
{
|
||||
foo_iface->do_something = meta_bar_do_something;
|
||||
}
|
||||
```
|
||||
|
||||
### Auxiliary Functions
|
||||
|
||||
Auxiliary functions are above every other functions to minimize the number of
|
||||
function prototypes in the file. These functions often grow when factoring out
|
||||
the same code between two or more functions:
|
||||
|
||||
```c
|
||||
static void
|
||||
do_something_on_data (Foo *data,
|
||||
Bar *bar)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
random_function (Foo *foo)
|
||||
{
|
||||
do_something_on_data (foo, bar);
|
||||
}
|
||||
|
||||
static void
|
||||
another_random_function (Foo *foo)
|
||||
{
|
||||
do_something_on_data (foo, bar);
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes, however, auxiliary functions are created to break down otherwise
|
||||
large functions - in this case, it is appropriate to keep these auxiliary
|
||||
functions close to the function they are tightly related to.
|
||||
|
||||
Auxiliary function names must have a verb in the imperative form, and should
|
||||
always perform an action over something. They usually don't have the class
|
||||
prefix (`meta_`, `clutter_`, or `cogl_`). For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
do_something_on_data (Foo *data,
|
||||
Bar *bar)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
Exceptionally, when converting between types, auxiliary function names may
|
||||
have the class prefix to this rule. For example:
|
||||
|
||||
```c
|
||||
static MetaFoo *
|
||||
meta_foo_from_bar (Bar *bar)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### Callback Functions
|
||||
|
||||
Callback function names should have the name of the action in imperative
|
||||
form. They don't have any prefix, but have a `_func` suffix. For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
filter_something_func (Foo *foo,
|
||||
Bar *bar,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### Signal Callbacks
|
||||
|
||||
Signal callbacks generally have the signal name. They should be prefixed with
|
||||
`on_`, or suffixed with `_cb`, but not both. For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
on_realize (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_cb (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
When the callback is named after the object that generated it, and the signal,
|
||||
then passive voice is used. For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
click_action_clicked_cb (ClutterClickAction *click_action,
|
||||
ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
[gnome-coding-style]: https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en
|
463
NEWS
463
NEWS
@ -1,440 +1,3 @@
|
||||
41.1
|
||||
====
|
||||
* Fix monitor screencast scanouts [Michel; !1914]
|
||||
* dma-buf: Use alpha-less pixel formats where appropriate [Robert; !1810]
|
||||
* wayland: Allow clients to maximize windows regardless of constraints
|
||||
[Christian; !1997]
|
||||
* Handle hotplug events without relevant changes more effectively
|
||||
[Marco; !1964]
|
||||
* Improve error reporting when startup fails [Jonas; !1994]
|
||||
* dma-buf: Add support for ABGR and XBGR formats [Erfan; !1999]
|
||||
* Fix X11 middle button emulation setting [José; !2000]
|
||||
* Include server-side shadows in window screenshots [Robert; !1996]
|
||||
* Don't change workspaces of unmanaged windows [Sebastian; !2003]
|
||||
* Reset idletime when unplugging the power cable [Bastien; !2029]
|
||||
* xwayland: Avoid unnecessary _NET_WM_STATE events [Dor; !2032]
|
||||
* Fix videos in Firefox stuttering in overview [Robert; !2034]
|
||||
* Don't use atomic mode setting for virtio_gpu driver [Jonas; !2040]
|
||||
* Improve on-screen keyboard on X11 [Sebastian, Ray; !1955, !2039]
|
||||
* misc [Daniel, Jonas, Corentin, Robert; !1992, !2007, !2008, !2026, !2044]
|
||||
* Fix text glitches after size changes [Sebastian; !2006]
|
||||
* Fix reporting output rotation to xwayland [Olivier; !2050]
|
||||
* wayland: Accept final preference of drop destination [Robert; !2043]
|
||||
* Fix erratic scrolling in GTK apps [Carlos; gnome-shell#4647]
|
||||
* Fix tilt direction of pen/tablet inputs [Quytelda; !2065]
|
||||
* Use b/w unicode for tablet mode OSD [Carlos; !2064]
|
||||
* Fix negative paint volume offscreen effect [Sebastian; !2031]
|
||||
* Only add paint volumes of mapped actors to stage clip [Robert; !2035]
|
||||
* Fix mapping tablet input to correct monitor [Jason; !1934]
|
||||
* Misc. bug fixes and cleanups
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Erfan Abdi, Dor Askayo, Michel Dänzer,
|
||||
José Expósito, Olivier Fourdan, Carlos Garnacho, Jason Gerecke,
|
||||
Quytelda Kahja, Sebastian Keller, Robert Mader, Bastien Nocera, Corentin Noël,
|
||||
Christian Rauch, Ray Strode, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
eshagh shahidani [fa], Danial Behzadi [fa], Марко Костић [sr],
|
||||
Zander Brown [en_GB], Ngọc Quân Trần [vi], Rūdolfs Mazurs [lv]
|
||||
|
||||
41.0
|
||||
====
|
||||
* Avoid race in wl_seat capabilities [Olivier; !77]
|
||||
* Expose option groups/entries to introspection [Corentin; !1976]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan, Corentin Noël
|
||||
|
||||
Translators:
|
||||
Daniel Șerbănescu [ro], Goran Vidović [hr], Luna Jernberg [sv],
|
||||
eshagh shahidani [fa], Gwan-gyeong Mun [ko], Emin Tufan Çetin [tr],
|
||||
Philipp Kiemle [de], Balázs Úr [hu], Piotr Drąg [pl], Nathan Follens [nl],
|
||||
Jordi Mas [ca], Ask Hjorth Larsen [da]
|
||||
|
||||
41.rc
|
||||
=====
|
||||
* Add clutter_stage_paint_to_content() [Ivan; !1899]
|
||||
* Add meta_cursor_tracker_get_scale() [Ivan; !1967]
|
||||
* wayland: Make each wl_output correspond to one monitor [Jonas; !1712]
|
||||
* Expose 'inactive-since' timestamp to uresourced [Nishal; !1960]
|
||||
* Pass dirty rects to secondary GPU [Piotr; !1879]
|
||||
* Support commiting preedit string on focus loss [Carlos; !1940]
|
||||
* Improve auto-rotation support [Marco; !1233]
|
||||
* Add meta_window_actor_paint_to_content() [Robert; !1893]
|
||||
* Fixed crashes [Jonas, Ray, Robert; !1947, !1979, !1965, !1958]
|
||||
* Misc. bug fixes and cleanups [Florian, Carlos, Robert, Daniel, Erico, Dor;
|
||||
!1957, !1924, !1970, !1971, !1972, !1973, !1974, !1977, !1978, !1975, !1886,
|
||||
!1983, !1990, !1980]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Dor Askayo, Carlos Garnacho, Nishal Kulkarni,
|
||||
Piotr Lopatka, Robert Mader, Ivan Molodetskikh, Florian Müllner, Erico Nunes,
|
||||
Ray Strode, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Asier Sarasua Garmendia [eu], Claude Paroz [fr], Jiri Grönroos [fi],
|
||||
Baurzhan Muftakhidinov [kk], Aurimas Černius [lt]
|
||||
|
||||
41.beta
|
||||
=======
|
||||
* Fix mouse position in remote desktop with fractional scaling [Pascal; !1867]
|
||||
* Manage idle monitors via MetaIdleManager [Jonas Å.; !1859]
|
||||
* Disable KMS modifiers on radeon driver [Carlos; !1872]
|
||||
* Fix fd leak [Carlos; !1870]
|
||||
* Fix adding virtual monitor to physical session [Jonas Å.; !1891]
|
||||
* Unbreak press-drag-release to pop up and select right click menus
|
||||
[Carlos; !1885]
|
||||
* Fix VKMS detection [Jonas Å.; !1892]
|
||||
* Fix swipe cancellation [JoseExposito; !1857]
|
||||
* Add ClutterTextureContent [Robert; !1888]
|
||||
* Fix mapping tablet to monitor [Christoph; !1887]
|
||||
* Fix area screencasts when window is unredirected [Michel; !1902]
|
||||
* Don't require a newly attached buffer to apply state [Christian, Jonas; !1795]
|
||||
* Close unused mode setting and rendering devices [Jonas Å.; !1828]
|
||||
* Only support super+scroll on wayland [Florian; !1922]
|
||||
* Implement the xdg-activation protocol [Carlos; !1845]
|
||||
* Reduce input latency by computing max render time heuristically [Ivan; !1762]
|
||||
* Apply dithering to dispatch time when needed [Daniel; !1826]
|
||||
* Introduce MetaContext [Jonas Å.; !1861]
|
||||
* x11: Compute monitor scale per output [Marco; !336]
|
||||
* Shrink and optimize the rounded-background-clip shader [Daniel; !1860]
|
||||
* remote-desktop: Handle non-responding selection owners [Pascal; !1874]
|
||||
* Improve sysprof support [Jonas Å.; !1700]
|
||||
* Allow clients to delegate titlebar gestures to the compositor [Florian; !1944]
|
||||
* Fix upside-down Xshape surface with EGLstream [Robert; !1937]
|
||||
* Fix 'kms-modifiers' experimental setting [Robert; !1953]
|
||||
* Make default focus window on each workspace appear focused [Alexander; !850]
|
||||
* Plugged memory leaks [Jonas Å.; !1869]
|
||||
* Fixed crashes crash [Daniel, Jonas Å., Florian; !1883, !1895,
|
||||
!1910, !1925, !1956]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Marco, Daniel, Florian, Georges,
|
||||
Zander, Carlos, Robert; !1833, !1863, !1876, !1873, !1884, !1890, !1900,
|
||||
!1912, !1916, !1911, !1920, !1865, !1927, !1923, !1929, !1100, !1932, !1931,
|
||||
!1862, !1933, !1930, !1935, !1936, !1878, !1938, !1942, !1951, !522, !1941]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Zander Brown, Piotr Drąg, Michel Dänzer,
|
||||
Carlos Garnacho, JoseExposito, Robert Mader, Alexander Mikhaylenko,
|
||||
Ivan Molodetskikh, Florian Müllner, Georges Basile Stavracas Neto,
|
||||
Pascal Nowack, Christian Rauch, Christoph Trassl, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Pawan Chitrakar [ne], Charles Monzat [fr], Dušan Kazik [sk],
|
||||
Quentin PAGÈS [oc], Alexey Rubtsov [ru], Alexander Shopov [bg],
|
||||
Florentina Mușat [ro], Chao-Hsiung Liao [zh_TW], Yuri Chornoivan [uk],
|
||||
Fran Dieguez [gl], Hugo Carvalho [pt], Rafael Fontenelle [pt_BR],
|
||||
Fabio Tomat [fur], Kukuh Syafaat [id], Yaron Shahrabani [he],
|
||||
Marek Černocký [cs], Matej Urbančič [sl], Boyuan Yang [zh_CN],
|
||||
Daniel Mustieles [es]
|
||||
|
||||
40.1
|
||||
====
|
||||
* Prevent clients from pasting old selection data [Carlos; !1772]
|
||||
* Fix forward_key IM functionality on wayland [Takao; !1802]
|
||||
* Ensure valid window texture size after viewport changes [Robert; !1799]
|
||||
* Only update cached paint volumes when necessary [Jonas D.; !1773, !1829]
|
||||
* Only disable KMS modifiers for drivers with known problems [Jonas Å; !1792]
|
||||
* Fix X11 client resize during moves [Olivier; !1777]
|
||||
* Fix performance drop during night light transition with Nvidia [Aaron; !1816]
|
||||
* kms: Don't add common modes that exceed the max bandwidth [Jonas Å.; !1834]
|
||||
* Create virtual input devices on demand [Jonas Å; !1800, !1858]
|
||||
* Fix wrong night light gamma when leaving power saving [Jonas Å.; !1835]
|
||||
* Fix picking edge case [Sebastian; !1842]
|
||||
* Properly tear down things when shutting down [Jonas Å.; !1822, !1856, !1853]
|
||||
* Fix monitor screencasting with fractional scaling [kirbykevinson; !1855]
|
||||
* Fixed crash [Carlos; !1849]
|
||||
* Plugged memory leak [Carlos; !1839]
|
||||
* Misc. bug fixes and cleanups [Carlos, Daniel, Jonas D., Jonas Å., Robert,
|
||||
Aleksandr, Florian, Michel, Sebastian, Olivier; !1785, !1798, !1784,
|
||||
!1791, !1801, !1807, !1786, !1793, !1804, !1820, !1824, !1819, !1803,
|
||||
!1821, !1806, !1814, !1831, !1832, !1836, !1843, !1740, !1841, !1827,
|
||||
!1844, !1852, !1850, !1851]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Michel Dänzer, Jonas Dreßler, Olivier Fourdan, Takao Fujiwara,
|
||||
Carlos Garnacho, Sebastian Keller, kirbykevinson, Robert Mader,
|
||||
Aleksandr Mezin, Florian Müllner, Aaron Plattner, Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Bruce Cowan [en_GB], Ngọc Quân Trần [vi], Marek Černocký [cs],
|
||||
Dz Chen [zh_CN], Yosef Or Boczko [he], Nathan Follens [nl],
|
||||
Yuri Chornoivan [uk], Jordi Mas [ca], Piotr Drąg [pl], Tim Sabsch [de],
|
||||
Luna Jernberg [sv], Hugo Carvalho [pt], Rafael Fontenelle [pt_BR],
|
||||
Asier Sarasua Garmendia [eu], Quentin PAGÈS [oc], Matej Urbančič [sl]
|
||||
|
||||
40.0
|
||||
====
|
||||
* xwayland: Check permissions on /tmp/.X11-unix [Olivier; !1787]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan
|
||||
|
||||
Translators:
|
||||
Hugo Carvalho [pt], Tim Sabsch [de], Daniel Mustieles [es],
|
||||
Matej Urbančič [sl], Марко Костић [sr], Fran Dieguez [gl]
|
||||
|
||||
40.rc
|
||||
=====
|
||||
* Fix keyboard input from remote desktop in Xorg session [Pascal; !1732]
|
||||
* Fix restoring focus to windows using globally active input [Olivier; !1716]
|
||||
* Expose unaccalerated touchpad gesture deltas [Alexander; !1353]
|
||||
* Avoid relayout on text attribute changes when possible [Jonas D.; !1750]
|
||||
* Add remote desktop caps- and num-lock state properties [Jonas Å.; !1739]
|
||||
* Improve refresh rate calculation [Akihiko; !1737]
|
||||
* Implement presentation-time protocol [Ivan; !1484]
|
||||
* Disable double-buffered shadow buffering [Jonas Å.; !1724]
|
||||
* Fix missing cursor on tablet devices [Jonas D.; !1758]
|
||||
* Fix frame timings causing X11 clients to get stuck [Jonas Å.; !1754]
|
||||
* Fix applying input settings on X11 [Marco, Suryashankar; !1769, !1767]
|
||||
* Add headless native backend [Jonas Å.; !1698]
|
||||
* Fix high latency and stalls with proprietary nvidia driver [Daniel; !1726]
|
||||
* Fix maximized windows not reacting to strut changes [Aleksandr; !1755]
|
||||
* Only start XWayland on demand when running under systemd [Benjamin; !1771]
|
||||
* Sync LEDs when a new input device is added [Olivier; !1662]
|
||||
* Fix order in which subsurface placement operations are handled [Robert; !1768]
|
||||
* Fixed crashes [Jonas Å., Sebastian; !1745, !1747, !1759, !1748, !1776, !1775]
|
||||
* Plugged leaks [Philip, Sebastian; !1738, !1728]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Ivan, Florian, Marco,
|
||||
Robert; !1688, !1744, !1736, !1749, !1752, !1753, !427, !1757, !1751, !1760,
|
||||
!1765, !1770, !1763, !1774, !1780, !1779, !1783]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Benjamin Berg, Suryashankar Das, Jonas Dreßler, Olivier Fourdan,
|
||||
Sebastian Keller, Robert Mader, Aleksandr Mezin, Alexander Mikhaylenko,
|
||||
Ivan Molodetskikh, Florian Müllner, Pascal Nowack, Akihiko Odaki,
|
||||
Marco Trevisan (Treviño), Daniel van Vugt, Philip Withnall
|
||||
|
||||
Translators:
|
||||
Fran Dieguez [gl], Asier Sarasua Garmendia [eu], Claude Paroz [fr],
|
||||
Piotr Drąg [pl], Hugo Carvalho [pt], Jordi Mas [ca], Fabio Tomat [fur],
|
||||
Yuri Chornoivan [uk], Enrico Nicoletto [pt_BR], Emin Tufan Çetin [tr],
|
||||
Daniel Șerbănescu [ro], Marek Černocký [cs], Balázs Úr [hu],
|
||||
Aurimas Černius [lt], Kukuh Syafaat [id], A S Alam [pa], Anders Jonsson [sv],
|
||||
Milo Casagrande [it], Gwan-gyeong Mun [ko]
|
||||
|
||||
40.beta
|
||||
=======
|
||||
* Consider clients without mapped windows for xwayland auto-shutdown
|
||||
[Olivier; !1671]
|
||||
* Let compositor to handle super+scroll events [Florian; !1674, !1695]
|
||||
* Default to starting Xwayland on demand [Olivier; !1673]
|
||||
* xwayland: Restore abstract socket support [James, Olivier; !1669]
|
||||
* Add support for atomic mode setting [Jonas Å.; !1488]
|
||||
* Fix clip region glitches when using fractional scaling [Daniel; !1554]
|
||||
* Default to horizontal workspace layout [Georges, Florian; !1684, !1706]
|
||||
* Do not ping unmanaging windows [Florian; gnome-shell#2467]
|
||||
* Handle monitor changes during screencasts [Jonas Å.; !1691]
|
||||
* Fix unexpected jumps after restoring misbehaving clients [Jonas Å.; !1445]
|
||||
* Fix newly opened X11 windows being invisible in overview [Olivier; !1678]
|
||||
* Fix viewport of offscreen effects [Daniel; !1053]
|
||||
* Fix drag cancel animation when using geometry scaling [Robert; !1683]
|
||||
* Improve touch-mode heuristics [Carlos; !1710]
|
||||
* Integrate clipboard with remote desktop sessions [Jonas Å.; !1552]
|
||||
* Fix stuck icon in DND operation between X11 and wayland [Carlos; !1720]
|
||||
* Automatically synchronize pointer position after modal grabs [Carlos; !1659]
|
||||
* Reimplement support for CLUTTER_SHOW_FPS [Daniel; !154]
|
||||
* Only pick on events that may move the pointer [Jonas D.; !1729, !1733]
|
||||
* Emit discrete scroll events for accumulated smooth events in virtual
|
||||
X11 devices [Pascal; !1727]
|
||||
* Add support for rounded clipping when drawing background [Jonas D.; !1717]
|
||||
* Plugged memory leaks [Sebastian; !1307, !1699]
|
||||
* Fixed crashes [Carlos, Thomas, Jonas Å., Olivier; !1677, !1685, !1692,
|
||||
!1719, !1718, !1735]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Carlos, Olivier, Sebastian, Björn,
|
||||
Jonas D., Ivan, Georges, Dor, Michel, Robert; !1670, !1679, !1680, !1682,
|
||||
!1681, !1661, !1689, !1690, !1693, !1514, !1696, !1697, !1708, !1709, !1707,
|
||||
!1701, !1702, !1715, !1725, !1734, !1512]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Dor Askayo, Björn Daase, Michel Dänzer, Jonas Dreßler,
|
||||
Olivier Fourdan, Carlos Garnacho, James Henstridge, Sebastian Keller,
|
||||
Robert Mader, Ivan Molodetskikh, Thomas Mühlbacher, Florian Müllner,
|
||||
Georges Basile Stavracas Neto, Pascal Nowack, Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Марко Костић [sr], Jordi Mas [ca], Yuri Chornoivan [uk],
|
||||
Daniel Șerbănescu [ro], Hugo Carvalho [pt], Fran Dieguez [gl],
|
||||
Matej Urbančič [sl], Marek Černocký [cs], Rafael Fontenelle [pt_BR],
|
||||
Philipp Kiemle [de], A S Alam [pa], Balázs Úr [hu], Anders Jonsson [sv],
|
||||
Daniel Mustieles [es], Emin Tufan Çetin [tr], Kukuh Syafaat [id],
|
||||
Aurimas Černius [lt]
|
||||
|
||||
40.alpha.1.1
|
||||
============
|
||||
* Adapt to settings moving to gsettings-desktop-schemas [Carlos; !1416]
|
||||
* Misc. bug fixes and cleanups [Georges; !1667]
|
||||
|
||||
Contributors:
|
||||
Carlos Garnacho, Georges Basile Stavracas Neto
|
||||
|
||||
40.alpha.1
|
||||
==========
|
||||
* Base ClutterEffects on ClutterPaintNodes [Georges; !1340, !1355]
|
||||
* xwayland: Set xrandr primary output [Aleksandr; !1558]
|
||||
* Add paint node based blur support [Georges; !1627, !1646]
|
||||
* Disable CRTCs if there is no monitor [Kai-Heng; !1561]
|
||||
* Fix updates of mipmapped animated backgrounds [Daniel; !1664]
|
||||
* Allow remote desktop clients to specify scroll source [Pascal; !1636]
|
||||
* Support the color transform matrix RandR property on X11 [Aaron; !1048]
|
||||
* Plugged memory leaks [Jonas D.; !1632]
|
||||
* Fixed crashes [Jonas Å., Olivier, Carlos; !1557, !1648, !1643, !1654, !1663]
|
||||
* Misc. bug fixes and cleanups [Olivier, Niels, Carlos, Jonas Å., Florian,
|
||||
Jonas D., Daniel, Georges, Michel, Sebastian, Marc-Antoine; !1621, !1622,
|
||||
!1624, !1623, !1625, !1626, !1630, !1631, !1576, !1635, !1640, !1642,
|
||||
!1639, !1644, !1637, !1615, !1647, !1633, !1634, !1651, !1652, !1657,
|
||||
!1660, !1658, !1665, !1649, !1668, !1655]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Michel Dänzer, Jonas Dreßler, Kai-Heng Feng, Olivier Fourdan,
|
||||
Carlos Garnacho, Niels De Graef, Sebastian Keller, Aleksandr Mezin,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack,
|
||||
Marc-Antoine Perennou, Aaron Plattner, Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Kjartan Maraas [nb], Juliano de Souza Camargo [pt], Florentina Mușat [ro],
|
||||
Daniel Mustieles [es], Jordi Mas i Hernandez [ca], Fabio Tomat [fur],
|
||||
Philipp Kiemle [de], Asier Sarasua Garmendia [eu], Aurimas Černius [lt],
|
||||
Fran Dieguez [gl], Hugo Carvalho [pt], Matej Urbančič [sl]
|
||||
|
||||
40.alpha
|
||||
========
|
||||
* Replace CoglMatrix with graphene_matrix [Georges; !1439]
|
||||
* Allow to specify debug topics in MUTTER_DEBUG [Jonas Å.; !1465]
|
||||
* Fix unwanted position changes on window resize
|
||||
[Jonas Å., Olivier, Robert; !1477, !1495]
|
||||
* Do not disable the X Security extension by default [Olivier; !1485]
|
||||
* Fix _NET_WM_FRAME_DRAWN timestamps [Jonas Å.; !1494]
|
||||
* Fix tiling to the correct monitor [Florian; #1389]
|
||||
* Only snap to window edges when CTRL is pressed [Florian; #679609]
|
||||
* Add support for scroll button locking [Peter; !1432]
|
||||
* Clip Frustra [Georges; !1489]
|
||||
* Improve tablet-mode-switch support [Hans; !1506]
|
||||
* Fix missed redraws of newly-mapped actors [Jonas D.; !1366, #1494]
|
||||
* Gracefully handle Xwayland crashes [Carlos; !1447]
|
||||
* wayland: Provide previous window dimensions on restore [Christian; !801]
|
||||
* Remove the ClutterActor::paint signal [Jonas; !1522]
|
||||
* Fix background artifacts in magnifier [Daniel; #1480]
|
||||
* Use raycasting for picking [Georges; !1509]
|
||||
* Fix monitor tiling support on X11 [Jonas Å.; #1524]
|
||||
* Fix xwayland grabs for override-redirect windows [Olivier; !1254]
|
||||
* Fix device configuration not being picked up on X11 [Carlos; !1553]
|
||||
* Support tagging devices as primary GPU via udev [Jonas Å.; !1562]
|
||||
* Fix size hints with CSD [Olivier; !1594]
|
||||
* Fix unresponsive input after screen blank [Simon; !1601]
|
||||
* Cull actors when picking [Georges; !1520]
|
||||
* Handle input in a thread [Carlos; !1403]
|
||||
* Improve freezes when switching workspace [Jonas Å.; !1616]
|
||||
* Plugged memory leaks [Ray; !1225]
|
||||
* Fixed crashes [Christian, Olivier, Daniel, Robert, Jonas Å., Florian Z.,
|
||||
Simon, Carlos; #1481, !1529, !1519, !1534, #1521, !1563, !1604, !1605,
|
||||
!1607, !1612]
|
||||
* Misc. bug fixes and cleanups [Florian, Carlos, Olivier, Georges, Björn,
|
||||
Jonas Å., Julius, Corentin, Bastien, Robert, Daniel, Niels, Jonas D., Uday,
|
||||
Ian, Jordan, Piotr; !1473, !1472, !1438, #1449, !1475, !1474, !1481, !1466,
|
||||
!1483, !1427, !1413, !1103, !1467, !1339, !1297, #1384, !1491, !528, !1496,
|
||||
!1510, !1507, !1387, !1498, !1515, !1516, !1517, !1486, !1524, !1527, !1528,
|
||||
!1531, !1532, !1521, !1535, #1490, !1545, !1555, !1564, !1549, !1567, !1565,
|
||||
!1572, !1569, !1573, !1566, !1525, !1468, !1578, !1583, !1584, !1585, !1571,
|
||||
!1327, !1586, !1590, !1588, !1050, !1596, !1592, !1587, !1599, !1577, !1511,
|
||||
!1591, !1603, !1611, !1593, !1617, !1619]
|
||||
|
||||
Contributors:
|
||||
Björn Daase, Jonas Dreßler, Piotr Drąg, Olivier Fourdan, Carlos Garnacho,
|
||||
Hans de Goede, Niels De Graef, Peter Hutterer, Julius Lehmann, Robert Mader,
|
||||
Simon McVittie, Florian Müllner, Georges Basile Stavracas Neto,
|
||||
Bastien Nocera, Corentin Noël, Jordan Petridis, Uday Kiran Pichika,
|
||||
Christian Rauch, Ian Douglas Scott, Ray Strode, Daniel van Vugt,
|
||||
Florian Zwoch, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Juliano de Souza Camargo [pt], Ask Hjorth Larsen [da], Yuri Chornoivan [uk]
|
||||
|
||||
3.38.1
|
||||
======
|
||||
* Fix Night Light updates after DPMS [Jonas, Benjamin; #1392]
|
||||
* Fix button scrolling on X11 [Peter; !1431]
|
||||
* Always use correct font-dpi setting on X11 [Marco; !1444]
|
||||
* Improve handling of scanout failures [Jonas; #1410]
|
||||
* Fix middle/right button mixup in scroll button assignment [Peter; !1433]
|
||||
* Fix resizing of attached modal dialogs on wayland [Jonas; !1446]
|
||||
* Enable KMS modifiers on devices that need them [Karol; !1443]
|
||||
* Fix IM handling on X11 [Carlos; #1413]
|
||||
* Fix glitches in "undefined" screencast areas [Jonas; !1459]
|
||||
* Fix visual glitches on background with fractional scaling [Daniel; !1464]
|
||||
* Fix using correct refresh rate [Jonas; #1430]
|
||||
* Misc. bug fixes and cleanups [Daniel, Carlos, Robert, Simon, Sergio; !1362,
|
||||
!1448, !1452, !1273, !1454, !1429, !1460, !1458, !1463, !1462]
|
||||
* Plugged memory leaks [Ray; !1449, !1451]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Benjamin Berg, Sergio Costas, Carlos Garnacho,
|
||||
Karol Herbst, Peter Hutterer, Robert Mader, Simon McVittie, Ray Strode,
|
||||
Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Juliano de Souza Camargo [pt], Rafael Fontenelle [pt_BR],
|
||||
Yosef Or Boczko [he], Jordi Mas [ca]
|
||||
|
||||
3.38.0
|
||||
======
|
||||
* screencast: Only use DMA buffers for i915 [Jonas; !1442]
|
||||
* Fixed crashes [Jonas, Simon; !1430, #1414]
|
||||
|
||||
Contributors:
|
||||
Simon McVittie, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Anders Jonsson [sv], Gil Forcada [ca], Balázs Meskó [hu], Tim Sabsch [de],
|
||||
Milo Casagrande [it], Bruce Cowan [en_GB], Rūdolfs Mazurs [lv]
|
||||
|
||||
3.37.92
|
||||
=======
|
||||
* Fix stale cursor positions in remote desktop sessions [Georges; !1417]
|
||||
* xwayland: Add a setting to disable selected X extensions [Olivier; !1405]
|
||||
* Fix screencasting when using QXL [Jonas Å., Grey; !1318]
|
||||
* Cull actors that don't intersect with the redraw clip [Daniel; !1359]
|
||||
* Optimize painting of backgrounds when culling is unavailable [Daniel; !1363]
|
||||
* Improve support for Hangul input method [Carlos; !1286]
|
||||
* Support debug paint overlay for opaque regions [Robert; !1372]
|
||||
* Fix launching flatpak applications when autostarting Xwayland [Carlos; !1424]
|
||||
* Add support for capture scanouts in screencasts [Georges; !1421]
|
||||
* Allow integrated tablet devices to cycle outputs [Carlos; !1201]
|
||||
* Improve mapping input devices to the most relevant output [Carlos; !1202]
|
||||
* Only enable auto-rotation in touch mode [Carlos; !1311]
|
||||
* Fixed crashes [Pascal, Robert, Carlos, Benjamin, Marco; !1414, !1409, !1408,
|
||||
!1415, #1395, !1392, !1371, #1345]
|
||||
* Misc. bug fixes and cleanups [Björn, Jonas D., Florian; !1410, !1358, !1425]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Benjamin Berg, Grey Christoforo, Björn Daase,
|
||||
Jonas Dreßler, Olivier Fourdan, Carlos Garnacho, Robert Mader,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack,
|
||||
Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Marek Černocký [cs], Aurimas Černius [lt], Asier Sarasua Garmendia [eu],
|
||||
Gwan-gyeong Mun [ko], Yuri Chornoivan [uk], Boyuan Yang [zh_CN],
|
||||
Kukuh Syafaat [id], Piotr Drąg [pl], Rafael Fontenelle [pt_BR],
|
||||
Марко Костић [sr], Matej Urbančič [sl], Fabio Tomat [fur],
|
||||
Daniel Mustieles [es], Fran Dieguez [gl], Goran Vidović [hr],
|
||||
Claude Paroz [fr], Andre Klapper [or, ug, te], Emin Tufan Çetin [tr]
|
||||
|
||||
3.37.91
|
||||
=======
|
||||
* Fix initial state of display mode OSD [Jian-Hong; #1362]
|
||||
* Fixed crashes [Jonas Å., Robert; !1407, !1411]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Christian; !1404, !1364, #1331]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Robert Mader, Jian-Hong Pan, Christian Rauch
|
||||
|
||||
Translators:
|
||||
Fran Dieguez [gl], Daniel Mustieles [es], Florentina Mușat [ro],
|
||||
Kukuh Syafaat [id], Piotr Drąg [pl], Emin Tufan Çetin [tr], Марко Костић [sr],
|
||||
Akarshan Biswas [bn_IN], Matej Urbančič [sl], Boyuan Yang [zh_CN],
|
||||
Goran Vidović [hr], Rafael Fontenelle [pt_BR]
|
||||
|
||||
3.37.90
|
||||
=======
|
||||
* Fix using NEAREST filter for backgrounds on scaled monitors [Daniel V.; !1346]
|
||||
@ -994,7 +557,7 @@ Contributors:
|
||||
3.31.92
|
||||
=======
|
||||
* Fix flicker of apps that use multiple SHM buffers [Jonas Å.; #199]
|
||||
* Don't disable page flips after temporary failures [Jonas Å.; #460]
|
||||
* Don't disable page flips after temporary failues [Jonas Å.; #460]
|
||||
* Improve redraw performance [Carlos; !196]
|
||||
* Add cursor-mode support to window screencasting [Jonas Å.; !413]
|
||||
* Add back support for system-wide monitor configurations [Jonas Å.; !253]
|
||||
@ -1406,7 +969,7 @@ Translations:
|
||||
=======
|
||||
* Reduce memory use of suspended instances [Jonas; #786299]
|
||||
* Make supported scales determination saner [Rui; #786474]
|
||||
* Fix crash on inhibit-shortcuts dialog response [Jonas; #786385]
|
||||
* Fix crash on inhibit-shortcuts dialog reponse [Jonas; #786385]
|
||||
* Support libinput's tag-and-drag setting [freeroot; #775755]
|
||||
* Avoid overlapping keybindings with multiple layouts [Jonas; #786408]
|
||||
* Fix non-transformed cursor on rotated monitors [Jonas; #786023]
|
||||
@ -1725,7 +1288,7 @@ Translations:
|
||||
* Consider XDG_SESSION_TYPE when determining session type [Jouke; #759388]
|
||||
* Re-add support for edge scrolling on some touchpads [Bastien; #768245]
|
||||
* Support mouse and trackball acceleration profile [Jonas; #769179]
|
||||
* Draw monitor content to individual framebuffer [Jonas; #768976]
|
||||
* Draw monitor contentn to individual framebuffer [Jonas; #768976]
|
||||
* Support virtual input devices [Jonas, Carlos; #765009]
|
||||
* Set correct output scale on hotplug [Jonas; #769505]
|
||||
* Misc. bug fixes and cleanups [Florian, Jonas, Thomas, Bastien, Carlos;
|
||||
@ -2550,7 +2113,7 @@ Translations:
|
||||
* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399]
|
||||
* Don't save pixbuf data in user data [Tim; #706777]
|
||||
* Don't queue redraws for obscured regions [Adel; #703332]
|
||||
* Support the opaque region hints for wayland clients [Jasper; #707019]
|
||||
* Suppor the opaque region hints for wayland clients [Jasper; #707019]
|
||||
* Turn blending off when drawing entirely opaque regions [Jasper; #707019]
|
||||
* Check event timestamps before reconfiguring [Giovanni; #706735]
|
||||
* Merge the DBus API for display configuration in the wayland branch [Giovanni]
|
||||
@ -3035,7 +2598,7 @@ Translations:
|
||||
======
|
||||
* Automaximize large windows on map [Adel; #671677]
|
||||
* When unmaximizing windows, make sure the unminimized size
|
||||
is significantly less than the maximized size [Adel; #671677]
|
||||
is signficantly less than the maximized size [Adel; #671677]
|
||||
* Don't offer maximize option for windows larger than the screen
|
||||
[Jasper; #643606]
|
||||
* Always focus the window immediately underneath without restacking
|
||||
@ -3135,7 +2698,7 @@ Translations:
|
||||
* Move from GConf to GSettings for preferences [Florian; #635378]
|
||||
* Add meta_display_add_keybinding()/meta_display_remove_keybinding()
|
||||
to allow creating new keybindings at runtime [Florian; #663428]
|
||||
* Add support for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE
|
||||
* Add suport for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE
|
||||
to allow applications to draw unfocused windows differently
|
||||
[Rui; #661427]
|
||||
* Add meta_window_move_resize_frame() to allow specifying the
|
||||
@ -3247,7 +2810,7 @@ Contributors:
|
||||
for easy resizing with thin borders. (New draggable_border_width GConf key
|
||||
controls the total width of visible and invisible borders.)
|
||||
[Jasper; #644930]
|
||||
* Draw rounded window corners with antialiasing [Jasper; #628195]
|
||||
* Draw rounded window corners with antialising [Jasper; #628195]
|
||||
* Unredirect override-redirect fullscreen windows, such as full-screen
|
||||
3D games to avoid any performance impact [Adel; #597014]
|
||||
* Add :resizable and :above properties to MetaWindow. [Tim; #653858]
|
||||
@ -3340,7 +2903,7 @@ Translations:
|
||||
3.0.2.1
|
||||
=======
|
||||
* When saving the session, use the "program name" rather than
|
||||
hardcoding mutter, fixing session saving for gnome-shell [Matthias]
|
||||
harcoding mutter, fixing session saving for gnome-shell [Matthias]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=648828
|
||||
|
||||
Contributors:
|
||||
@ -3658,7 +3221,7 @@ Bugs fixed:
|
||||
634779 MetaWindowGroup: further optimize paints by using current scissor
|
||||
634833 Draw the root window background
|
||||
592382 improve shadow effect
|
||||
628199 Add antialiasing to arc and line drawing operations
|
||||
628199 Add antialising to arc and line drawing operations
|
||||
633002 meta-actor-window: Use G_UNLIKELY for TFP check
|
||||
634771 MetaStackTracker: Avoid queueing resync for obvious no-ops
|
||||
635421 Fix crash in check_needs_shadow
|
||||
@ -3855,7 +3418,7 @@ Fixed Bugs:
|
||||
- Allow a theme to turn on title ellipsization
|
||||
* Performance enhancements:
|
||||
- Stream raw damage updates to ClutterX11TexturePixmap
|
||||
to enable partial stage updates when windows change [Robert]
|
||||
to enable partial stage updates when windos change [Robert]
|
||||
- Don't trap XErrors in meta_compositor_process_event [Adel]
|
||||
* Add meta_prefs_override_preference_location(); this allows
|
||||
a plugin like GNOME Shell to redirect preferences to a
|
||||
@ -3900,7 +3463,7 @@ Fixed Bugs:
|
||||
613136 - remove over-restrictive assert from meta_prefs_get_workspace_name()
|
||||
613398 - Don't trap XErrors in meta_compositor_process_event
|
||||
615586 - Allow redirecting preferences to a different GConf key
|
||||
615672 - can't compile mutter error: dereferencing pointer ‘p’ does break
|
||||
615672 - cant' compile mutter error: dereferencing pointer ‘p’ does break
|
||||
strict-aliasing rules
|
||||
616050 - alt-tab infrastructure patches
|
||||
616274 - mutter from git fails with gcc 4.5 (on new warning)
|
||||
@ -4846,7 +4409,7 @@ Arthur Taylor, Elijah Newren, Josselin Mouette, Havoc Pennington,
|
||||
Benjamin Berg, and Carlo Wood for improvements in this release.
|
||||
|
||||
- new icon for the force-quit dialog (Jaap) [#396655]
|
||||
- add configurable mouse click action abilities, and clean up lots of
|
||||
- add configureable mouse click action abilities, and clean up lots of
|
||||
related code (Linus) [#408899, #408902, others]
|
||||
- add schemeas for middle and right click titlebar actions (Charlie)
|
||||
[#408903]
|
||||
@ -5400,7 +4963,7 @@ this release.
|
||||
running with --disable-gconf. Make --disable-gconf actually work.
|
||||
(Elijah) [#326661]
|
||||
- fix some reading-from-free'd-data errors (Søren) [#327575]
|
||||
- fix an uninitialized value problem when in raise-on-click mode
|
||||
- fix an unitialized value problem when in raise-on-click mode
|
||||
(Søren) [#327572]
|
||||
- avoid flashing original-sized window when closing a maximized
|
||||
window (Elijah) [#317254]
|
||||
|
31
README.md
31
README.md
@ -26,34 +26,15 @@ debugging purposes.
|
||||
|
||||
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter.
|
||||
|
||||
It can be useful to look at the documentation available at the
|
||||
[Wiki](https://gitlab.gnome.org/GNOME/mutter/-/wikis/home).
|
||||
|
||||
## Coding style and conventions
|
||||
|
||||
See [HACKING.md](./HACKING.md).
|
||||
|
||||
## Git messages
|
||||
The coding style used is primarily the GNU flavor of the [GNOME coding
|
||||
style](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en)
|
||||
with some minor additions such as preferring `stdint.h` types over GLib
|
||||
fundamental types, and a soft 80 character line limit. However, in general,
|
||||
look at the file you're editing for inspiration.
|
||||
|
||||
Commit messages should follow the [GNOME commit message
|
||||
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
|
||||
to either an issue or a merge request in each commit. Try to always prefix
|
||||
commit subjects with a relevant topic, such as `compositor:` or
|
||||
`clutter/actor:`, and it's always better to write too much in the commit
|
||||
message body than too little.
|
||||
|
||||
## Default branch
|
||||
|
||||
The default development branch is `main`. If you still have a local
|
||||
checkout under the old name, 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
|
||||
```
|
||||
to either an issue or a merge request in each commit.
|
||||
|
||||
## License
|
||||
|
||||
|
138
check-style.py
138
check-style.py
@ -1,138 +0,0 @@
|
||||
#!/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# Path relative to this script
|
||||
uncrustify_cfg = 'tools/uncrustify.cfg'
|
||||
|
||||
def run_diff(sha):
|
||||
proc = subprocess.Popen(["git", "diff", "-U0", "--function-context", sha, "HEAD"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
files = proc.stdout.read().strip().decode('utf-8')
|
||||
return files.split('\n')
|
||||
|
||||
def find_chunks(diff):
|
||||
file_entry_re = re.compile('^\+\+\+ b/(.*)$')
|
||||
diff_chunk_re = re.compile('^@@ -\d+,\d+ \+(\d+),(\d+)')
|
||||
file = None
|
||||
chunks = []
|
||||
|
||||
for line in diff:
|
||||
match = file_entry_re.match(line)
|
||||
if match:
|
||||
file = match.group(1)
|
||||
|
||||
match = diff_chunk_re.match(line)
|
||||
if match:
|
||||
start = int(match.group(1))
|
||||
len = int(match.group(2))
|
||||
end = start + len
|
||||
|
||||
if len > 0 and (file.endswith('.c') or file.endswith('.h') or file.endswith('.vala')):
|
||||
chunks.append({ 'file': file, 'start': start, 'end': end })
|
||||
|
||||
return chunks
|
||||
|
||||
def reformat_chunks(chunks, rewrite):
|
||||
# Creates temp file with INDENT-ON/OFF comments
|
||||
def create_temp_file(file, start, end):
|
||||
with open(file) as f:
|
||||
tmp = tempfile.NamedTemporaryFile()
|
||||
tmp.write(b'/** *INDENT-OFF* **/\n')
|
||||
for i, line in enumerate(f):
|
||||
if i == start - 2:
|
||||
tmp.write(b'/** *INDENT-ON* **/\n')
|
||||
|
||||
tmp.write(bytes(line, 'utf-8'))
|
||||
|
||||
if i == end - 2:
|
||||
tmp.write(b'/** *INDENT-OFF* **/\n')
|
||||
|
||||
tmp.seek(0)
|
||||
|
||||
return tmp
|
||||
|
||||
# Removes uncrustify INDENT-ON/OFF helper comments
|
||||
def remove_indent_comments(output):
|
||||
tmp = tempfile.NamedTemporaryFile()
|
||||
|
||||
for line in output:
|
||||
if line != b'/** *INDENT-OFF* **/\n' and line != b'/** *INDENT-ON* **/\n':
|
||||
tmp.write(line)
|
||||
|
||||
tmp.seek(0)
|
||||
|
||||
return tmp
|
||||
|
||||
changed = None
|
||||
|
||||
for chunk in chunks:
|
||||
# Add INDENT-ON/OFF comments
|
||||
tmp = create_temp_file(chunk['file'], chunk['start'], chunk['end'])
|
||||
|
||||
# uncrustify chunk
|
||||
proc = subprocess.Popen(["uncrustify", "-c", uncrustify_cfg, "-f", tmp.name], stdout=subprocess.PIPE)
|
||||
reindented = proc.stdout.readlines()
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
continue
|
||||
|
||||
tmp.close()
|
||||
|
||||
# Remove INDENT-ON/OFF comments
|
||||
formatted = remove_indent_comments(reindented)
|
||||
|
||||
if dry_run is True:
|
||||
# Show changes
|
||||
proc = subprocess.Popen(["diff", "-up", "--color=always", chunk['file'], formatted.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
diff = proc.stdout.read().decode('utf-8')
|
||||
if diff != '':
|
||||
output = re.sub('\t', '↦\t', diff)
|
||||
print(output)
|
||||
changed = True
|
||||
else:
|
||||
# Apply changes
|
||||
diff = subprocess.Popen(["diff", "-up", chunk['file'], formatted.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
patch = subprocess.Popen(["patch", chunk['file']], stdin=diff.stdout)
|
||||
diff.stdout.close()
|
||||
patch.communicate()
|
||||
|
||||
formatted.close()
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='Check code style.')
|
||||
parser.add_argument('--sha', metavar='SHA', type=str,
|
||||
help='SHA for the commit to compare HEAD with')
|
||||
parser.add_argument('--dry-run', '-d', type=bool,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help='Only print changes to stdout, do not change code')
|
||||
parser.add_argument('--rewrite', '-r', type=bool,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help='Whether to amend the result to the last commit (e.g. \'git rebase --exec "%(prog)s -r"\')')
|
||||
|
||||
# Change CWD to script location, necessary for always locating the configuration file
|
||||
os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
|
||||
|
||||
args = parser.parse_args()
|
||||
sha = args.sha or 'HEAD^'
|
||||
rewrite = args.rewrite
|
||||
dry_run = args.dry_run
|
||||
|
||||
diff = run_diff(sha)
|
||||
chunks = find_chunks(diff)
|
||||
changed = reformat_chunks(chunks, rewrite)
|
||||
|
||||
if dry_run is not True and rewrite is True:
|
||||
proc = subprocess.Popen(["git", "commit", "--all", "--amend", "-C", "HEAD"], stdout=subprocess.DEVNULL)
|
||||
os._exit(0)
|
||||
elif dry_run is True and changed is True:
|
||||
print ("\nIssue the following command in your local tree to apply the suggested changes (needs uncrustify installed):\n\n $ git rebase origin/main --exec \"./check-style.py -r\" \n")
|
||||
os._exit(-1)
|
||||
|
||||
os._exit(0)
|
@ -28,7 +28,7 @@
|
||||
#include "cally-actor.h"
|
||||
|
||||
/*
|
||||
* Auxiliary define, in order to get the clutter actor from the AtkObject using
|
||||
* Auxiliar define, in order to get the clutter actor from the AtkObject using
|
||||
* AtkGObject methods
|
||||
*
|
||||
*/
|
||||
|
@ -72,7 +72,9 @@
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#ifdef CLUTTER_WINDOWING_X11
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@ -765,11 +767,10 @@ static gboolean
|
||||
cally_actor_action_do_action (AtkAction *action,
|
||||
gint index)
|
||||
{
|
||||
CallyActor *cally_actor = NULL;
|
||||
AtkStateSet *set = NULL;
|
||||
CallyActorPrivate *priv = NULL;
|
||||
CallyActorActionInfo *info = NULL;
|
||||
gboolean did_action = FALSE;
|
||||
CallyActor *cally_actor = NULL;
|
||||
AtkStateSet *set = NULL;
|
||||
CallyActorPrivate *priv = NULL;
|
||||
CallyActorActionInfo *info = NULL;
|
||||
|
||||
cally_actor = CALLY_ACTOR (action);
|
||||
priv = cally_actor->priv;
|
||||
@ -777,19 +778,21 @@ cally_actor_action_do_action (AtkAction *action,
|
||||
set = atk_object_ref_state_set (ATK_OBJECT (cally_actor));
|
||||
|
||||
if (atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!atk_state_set_contains_state (set, ATK_STATE_SENSITIVE) ||
|
||||
!atk_state_set_contains_state (set, ATK_STATE_SHOWING))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
g_object_unref (set);
|
||||
|
||||
info = _cally_actor_get_action_info (cally_actor, index);
|
||||
|
||||
if (info == NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (info->do_action_func == NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!priv->action_queue)
|
||||
priv->action_queue = g_queue_new ();
|
||||
@ -799,12 +802,7 @@ cally_actor_action_do_action (AtkAction *action,
|
||||
if (!priv->action_idle_handler)
|
||||
priv->action_idle_handler = g_idle_add (idle_do_action, cally_actor);
|
||||
|
||||
did_action = TRUE;
|
||||
|
||||
out:
|
||||
g_clear_object (&set);
|
||||
|
||||
return did_action;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -970,7 +968,7 @@ cally_actor_real_notify_clutter (GObject *obj,
|
||||
* paint it; we don't want this to generate an ATK
|
||||
* state change
|
||||
*/
|
||||
if (clutter_actor_is_painting_unmapped (actor))
|
||||
if (clutter_actor_is_in_clone_paint (actor))
|
||||
return;
|
||||
|
||||
state = ATK_STATE_SHOWING;
|
||||
@ -1086,7 +1084,7 @@ cally_actor_add_action_full (CallyActor *cally_actor,
|
||||
|
||||
priv = cally_actor->priv;
|
||||
|
||||
info = g_new0 (CallyActorActionInfo, 1);
|
||||
info = g_slice_new (CallyActorActionInfo);
|
||||
info->name = g_strdup (action_name);
|
||||
info->description = g_strdup (action_description);
|
||||
info->keybinding = g_strdup (action_keybinding);
|
||||
@ -1106,7 +1104,7 @@ cally_actor_add_action_full (CallyActor *cally_actor,
|
||||
*
|
||||
* Removes a action, using the @action_id returned by cally_actor_add_action()
|
||||
*
|
||||
* Return value: %TRUE if the operation was successful, %FALSE otherwise
|
||||
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
@ -1140,7 +1138,7 @@ cally_actor_remove_action (CallyActor *cally_actor,
|
||||
* Removes an action, using the @action_name used when the action was added
|
||||
* with cally_actor_add_action()
|
||||
*
|
||||
* Return value: %TRUE if the operation was successful, %FALSE otherwise
|
||||
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
@ -1191,5 +1189,5 @@ _cally_actor_destroy_action_info (gpointer action_info,
|
||||
if (info->notify)
|
||||
info->notify (info->user_data);
|
||||
|
||||
g_free (info);
|
||||
g_slice_free (CallyActorActionInfo, info);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj);
|
||||
/* AtkWindow */
|
||||
static void cally_stage_window_interface_init (AtkWindowIface *iface);
|
||||
|
||||
/* Auxiliary */
|
||||
/* Auxiliar */
|
||||
static void cally_stage_activate_cb (ClutterStage *stage,
|
||||
gpointer data);
|
||||
static void cally_stage_deactivate_cb (ClutterStage *stage,
|
||||
@ -134,11 +134,8 @@ cally_stage_notify_key_focus_cb (ClutterStage *stage,
|
||||
|
||||
if (self->priv->key_focus != NULL)
|
||||
{
|
||||
if (self->priv->key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
}
|
||||
g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
old = clutter_actor_get_accessible (self->priv->key_focus);
|
||||
}
|
||||
else
|
||||
@ -163,11 +160,8 @@ cally_stage_notify_key_focus_cb (ClutterStage *stage,
|
||||
*
|
||||
* we remove the weak pointer above.
|
||||
*/
|
||||
if (key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
}
|
||||
g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
|
||||
new = clutter_actor_get_accessible (key_focus);
|
||||
}
|
||||
@ -228,7 +222,7 @@ cally_stage_window_interface_init (AtkWindowIface *iface)
|
||||
/* At this moment AtkWindow is just about signals */
|
||||
}
|
||||
|
||||
/* Auxiliary */
|
||||
/* Auxiliar */
|
||||
static void
|
||||
cally_stage_activate_cb (ClutterStage *stage,
|
||||
gpointer data)
|
||||
|
@ -1513,7 +1513,7 @@ cally_text_get_offset_at_point (AtkText *text,
|
||||
}
|
||||
|
||||
|
||||
/******** Auxiliary private methods ******/
|
||||
/******** Auxiliar private methods ******/
|
||||
|
||||
/* ClutterText only maintains the current cursor position and a extra selection
|
||||
bound, but this could be before or after the cursor. This method returns
|
||||
@ -1552,7 +1552,7 @@ _cally_text_delete_text_cb (ClutterText *clutter_text,
|
||||
|
||||
g_return_if_fail (CALLY_IS_TEXT (data));
|
||||
|
||||
/* Ignore zero length deletions */
|
||||
/* Ignore zero lengh deletions */
|
||||
if (end_pos - start_pos == 0)
|
||||
return;
|
||||
|
||||
@ -1653,7 +1653,7 @@ cally_text_insert_text (AtkEditableText *text,
|
||||
clutter_text_insert_text (CLUTTER_TEXT (actor),
|
||||
string, *position);
|
||||
|
||||
/* we suppose that the text insertion will be successful,
|
||||
/* we suppose that the text insertion will be succesful,
|
||||
clutter-text doesn't warn about it. A option would be search for
|
||||
the text, but it seems not really required */
|
||||
*position += length;
|
||||
@ -1866,7 +1866,7 @@ static gint
|
||||
_cally_atk_attribute_lookup_func (gconstpointer data,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
AtkTextAttribute attr = (AtkTextAttribute) GPOINTER_TO_INT (user_data);
|
||||
AtkTextAttribute attr = (AtkTextAttribute) user_data;
|
||||
AtkAttribute *at = (AtkAttribute *) data;
|
||||
if (!g_strcmp0 (at->name, atk_text_attribute_get_name (attr)))
|
||||
return 0;
|
||||
|
@ -54,7 +54,7 @@ clutter_actor_box_new (gfloat x_1,
|
||||
ClutterActorBox *
|
||||
clutter_actor_box_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterActorBox, 1);
|
||||
return g_slice_new0 (ClutterActorBox);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,7 +130,7 @@ ClutterActorBox *
|
||||
clutter_actor_box_copy (const ClutterActorBox *box)
|
||||
{
|
||||
if (G_LIKELY (box != NULL))
|
||||
return g_memdup2 (box, sizeof (ClutterActorBox));
|
||||
return g_slice_dup (ClutterActorBox, box);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -148,7 +148,7 @@ void
|
||||
clutter_actor_box_free (ClutterActorBox *box)
|
||||
{
|
||||
if (G_LIKELY (box != NULL))
|
||||
g_free (box);
|
||||
g_slice_free (ClutterActorBox, box);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -320,7 +320,7 @@ clutter_actor_box_get_area (const ClutterActorBox *box)
|
||||
* @y: Y coordinate of the point
|
||||
*
|
||||
* Checks whether a point with @x, @y coordinates is contained
|
||||
* within @box
|
||||
* withing @box
|
||||
*
|
||||
* Return value: %TRUE if the point is contained by the #ClutterActorBox
|
||||
*
|
||||
@ -554,7 +554,7 @@ _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
|
||||
*
|
||||
* The reason this is important is because effects will use this
|
||||
* API to determine the size of offscreen framebuffers and so for
|
||||
* a fixed-size object that may be animated across the screen we
|
||||
* a fixed-size object that may be animated accross the screen we
|
||||
* want to make sure that the stage paint-box has an equally stable
|
||||
* size so that effects aren't made to continuously re-allocate
|
||||
* a corresponding fbo.
|
||||
@ -583,7 +583,7 @@ _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
|
||||
|
||||
/* Now we redefine the top-left relative to the bottom right based on the
|
||||
* rounded width/height determined above + a constant so that the overall
|
||||
* size of the box will be stable and not dependent on the box's
|
||||
* size of the box will be stable and not dependant on the box's
|
||||
* position.
|
||||
*
|
||||
* Adding 3px to the width/height will ensure we cover the maximum of
|
||||
|
@ -26,6 +26,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*< private >
|
||||
* ClutterRedrawFlags:
|
||||
* @CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION: Tells clutter the maximum
|
||||
* extents of what needs to be redrawn lies within the actors
|
||||
* current allocation. (Only use this for 2D actors though because
|
||||
* any actor with depth may be projected outside of its allocation)
|
||||
*
|
||||
* Flags passed to the clutter_actor_queue_redraw_with_clip ()
|
||||
* function
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION = 1 << 0
|
||||
} ClutterRedrawFlags;
|
||||
|
||||
/*< private >
|
||||
* ClutterActorTraverseFlags:
|
||||
* CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST: Traverse the graph in
|
||||
@ -163,10 +180,10 @@ struct _ClutterTransformInfo
|
||||
graphene_point_t pivot;
|
||||
gfloat pivot_z;
|
||||
|
||||
graphene_matrix_t transform;
|
||||
CoglMatrix transform;
|
||||
guint transform_set : 1;
|
||||
|
||||
graphene_matrix_t child_transform;
|
||||
CoglMatrix child_transform;
|
||||
guint child_transform_set : 1;
|
||||
};
|
||||
|
||||
@ -203,11 +220,11 @@ void _clutter_actor_traverse
|
||||
gpointer user_data);
|
||||
ClutterActor * _clutter_actor_get_stage_internal (ClutterActor *actor);
|
||||
|
||||
void _clutter_actor_apply_modelview_transform (ClutterActor *self,
|
||||
graphene_matrix_t *matrix);
|
||||
void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
|
||||
ClutterActor *ancestor,
|
||||
graphene_matrix_t *matrix);
|
||||
void _clutter_actor_apply_modelview_transform (ClutterActor *self,
|
||||
CoglMatrix *matrix);
|
||||
void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
|
||||
ClutterActor *ancestor,
|
||||
CoglMatrix *matrix);
|
||||
|
||||
void _clutter_actor_rerealize (ClutterActor *self,
|
||||
ClutterCallback callback,
|
||||
@ -228,21 +245,30 @@ void _clutter_actor_set_has_pointer
|
||||
void _clutter_actor_set_has_key_focus (ClutterActor *self,
|
||||
gboolean has_key_focus);
|
||||
|
||||
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
ClutterRedrawFlags flags,
|
||||
const ClutterPaintVolume *clip_volume);
|
||||
void _clutter_actor_queue_redraw_full (ClutterActor *self,
|
||||
ClutterRedrawFlags flags,
|
||||
const ClutterPaintVolume *volume,
|
||||
ClutterEffect *effect);
|
||||
|
||||
void _clutter_actor_finish_queue_redraw (ClutterActor *self);
|
||||
void _clutter_actor_finish_queue_redraw (ClutterActor *self,
|
||||
ClutterPaintVolume *clip);
|
||||
|
||||
gboolean _clutter_actor_set_default_paint_volume (ClutterActor *self,
|
||||
GType check_gtype,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
const char * _clutter_actor_get_debug_name (ClutterActor *self);
|
||||
const gchar * _clutter_actor_get_debug_name (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_push_clone_paint (void);
|
||||
void _clutter_actor_pop_clone_paint (void);
|
||||
|
||||
void _clutter_actor_shader_pre_paint (ClutterActor *actor,
|
||||
gboolean repeat);
|
||||
void _clutter_actor_shader_post_paint (ClutterActor *actor);
|
||||
|
||||
ClutterActorAlign _clutter_actor_get_effective_x_align (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_handle_event (ClutterActor *actor,
|
||||
@ -252,6 +278,8 @@ void _clutter_actor_attach_clone
|
||||
ClutterActor *clone);
|
||||
void _clutter_actor_detach_clone (ClutterActor *actor,
|
||||
ClutterActor *clone);
|
||||
void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
|
||||
void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
|
||||
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
|
||||
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
|
||||
|
||||
@ -260,17 +288,11 @@ float clutter_actor_get_real_resource_scale
|
||||
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
|
||||
CoglTexture *texture);
|
||||
|
||||
void clutter_actor_finish_layout (ClutterActor *self,
|
||||
int phase);
|
||||
void clutter_actor_update_stage_views (ClutterActor *self,
|
||||
int phase);
|
||||
|
||||
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
|
||||
|
||||
gboolean clutter_actor_is_painting_unmapped (ClutterActor *self);
|
||||
|
||||
gboolean clutter_actor_get_redraw_clip (ClutterActor *self,
|
||||
ClutterPaintVolume *dst_old_pv,
|
||||
ClutterPaintVolume *dst_new_pv);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -187,6 +187,7 @@ struct _ClutterActor
|
||||
* chain up to the parent's implementation
|
||||
* @pick: virtual function, used to draw an outline of the actor with
|
||||
* the given color
|
||||
* @queue_redraw: class handler for #ClutterActor::queue-redraw
|
||||
* @event: class handler for #ClutterActor::event
|
||||
* @button_press_event: class handler for #ClutterActor::button-press-event
|
||||
* @button_release_event: class handler for
|
||||
@ -238,6 +239,10 @@ struct _ClutterActorClass
|
||||
void (* pick) (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context);
|
||||
|
||||
gboolean (* queue_redraw) (ClutterActor *actor,
|
||||
ClutterActor *leaf_that_queued,
|
||||
ClutterPaintVolume *paint_volume);
|
||||
|
||||
/* size negotiation */
|
||||
void (* get_preferred_width) (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@ -252,7 +257,7 @@ struct _ClutterActorClass
|
||||
|
||||
/* transformations */
|
||||
void (* apply_transform) (ClutterActor *actor,
|
||||
graphene_matrix_t *matrix);
|
||||
ClutterMatrix *matrix);
|
||||
|
||||
/* event signals */
|
||||
gboolean (* event) (ClutterActor *actor,
|
||||
@ -586,8 +591,7 @@ void clutter_actor_set_offscreen_redirect
|
||||
CLUTTER_EXPORT
|
||||
ClutterOffscreenRedirect clutter_actor_get_offscreen_redirect (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_should_pick (ClutterActor *self,
|
||||
ClutterPickContext *pick_context);
|
||||
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
@ -799,16 +803,16 @@ void clutter_actor_get_translation
|
||||
gfloat *translate_z);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_transform (ClutterActor *self,
|
||||
const graphene_matrix_t *transform);
|
||||
const ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transform (ClutterActor *self,
|
||||
graphene_matrix_t *transform);
|
||||
ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_child_transform (ClutterActor *self,
|
||||
const graphene_matrix_t *transform);
|
||||
const ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_child_transform (ClutterActor *self,
|
||||
graphene_matrix_t *transform);
|
||||
ClutterMatrix *transform);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transformed_extents (ClutterActor *self,
|
||||
@ -931,9 +935,6 @@ GList * clutter_actor_peek_stage_views (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_invalidate_transform (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_invalidate_paint_volume (ClutterActor *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_H__ */
|
||||
|
@ -83,6 +83,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterZoomAction, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorBox, clutter_actor_box_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColor, clutter_color_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMargin, clutter_margin_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMatrix, clutter_matrix_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintContext, clutter_paint_context_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintNode, clutter_paint_node_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintVolume, clutter_paint_volume_free)
|
||||
|
@ -73,6 +73,7 @@ struct _ClutterBackendClass
|
||||
ClutterStageWindow * (* create_stage) (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error);
|
||||
void (* init_events) (ClutterBackend *backend);
|
||||
void (* init_features) (ClutterBackend *backend);
|
||||
void (* add_options) (ClutterBackend *backend,
|
||||
GOptionGroup *group);
|
||||
@ -115,6 +116,12 @@ gboolean _clutter_backend_pre_parse (Clutter
|
||||
gboolean _clutter_backend_post_parse (ClutterBackend *backend,
|
||||
GError **error);
|
||||
|
||||
void _clutter_backend_init_events (ClutterBackend *backend);
|
||||
void _clutter_backend_copy_event_data (ClutterBackend *backend,
|
||||
const ClutterEvent *src,
|
||||
ClutterEvent *dest);
|
||||
void _clutter_backend_free_event_data (ClutterBackend *backend,
|
||||
ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_backend_translate_event (ClutterBackend *backend,
|
||||
gpointer native,
|
||||
@ -139,9 +146,6 @@ float clutter_backend_get_fallback_resource_scale (ClutterBackend *backend);
|
||||
|
||||
gboolean clutter_backend_is_display_server (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_backend_destroy (ClutterBackend *backend);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-event-private.h"
|
||||
@ -50,8 +52,18 @@
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-stage-window.h"
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
#include "wayland/clutter-wayland-compositor.h"
|
||||
#endif
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <wayland-server.h>
|
||||
#include "wayland/clutter-wayland-compositor.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_FONT_NAME "Sans 10"
|
||||
|
||||
enum
|
||||
@ -67,6 +79,12 @@ G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT)
|
||||
|
||||
static guint backend_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
/* Global for being able to specify a compositor side wayland display
|
||||
* pointer before clutter initialization */
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
static struct wl_display *_wayland_compositor_display;
|
||||
#endif
|
||||
|
||||
static void
|
||||
clutter_backend_dispose (GObject *gobject)
|
||||
{
|
||||
@ -75,20 +93,28 @@ clutter_backend_dispose (GObject *gobject)
|
||||
/* clear the events still in the queue of the main context */
|
||||
_clutter_clear_events_queue ();
|
||||
|
||||
g_clear_object (&backend->dummy_onscreen);
|
||||
g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref);
|
||||
if (backend->stage_window)
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (backend->stage_window),
|
||||
(gpointer *) &backend->stage_window);
|
||||
backend->stage_window = NULL;
|
||||
}
|
||||
|
||||
g_clear_pointer (&backend->cogl_source, g_source_destroy);
|
||||
g_clear_pointer (&backend->font_name, g_free);
|
||||
g_clear_pointer (&backend->font_options, cairo_font_options_destroy);
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
||||
|
||||
g_source_destroy (backend->cogl_source);
|
||||
|
||||
g_free (backend->font_name);
|
||||
clutter_backend_set_font_options (backend, NULL);
|
||||
g_clear_object (&backend->input_method);
|
||||
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static gfloat
|
||||
@ -189,20 +215,22 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
CoglSwapChain *swap_chain;
|
||||
GError *internal_error;
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
|
||||
swap_chain = NULL;
|
||||
internal_error = NULL;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl renderer");
|
||||
backend->cogl_renderer = klass->get_renderer (backend, error);
|
||||
backend->cogl_renderer = klass->get_renderer (backend, &internal_error);
|
||||
|
||||
if (backend->cogl_renderer == NULL)
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Connecting the renderer");
|
||||
cogl_renderer_set_driver (backend->cogl_renderer, driver_id);
|
||||
if (!cogl_renderer_connect (backend->cogl_renderer, error))
|
||||
if (!cogl_renderer_connect (backend->cogl_renderer, &internal_error))
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl swap chain");
|
||||
@ -214,7 +242,7 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
backend->cogl_display = klass->get_display (backend,
|
||||
backend->cogl_renderer,
|
||||
swap_chain,
|
||||
error);
|
||||
&internal_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -230,7 +258,7 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
*/
|
||||
res = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
|
||||
tmpl,
|
||||
error);
|
||||
&internal_error);
|
||||
|
||||
if (!res)
|
||||
goto error;
|
||||
@ -244,12 +272,17 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
if (backend->cogl_display == NULL)
|
||||
goto error;
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
cogl_wayland_display_set_compositor_display (backend->cogl_display,
|
||||
_wayland_compositor_display);
|
||||
#endif
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Setting up the display");
|
||||
if (!cogl_display_setup (backend->cogl_display, error))
|
||||
if (!cogl_display_setup (backend->cogl_display, &internal_error))
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating the Cogl context");
|
||||
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
|
||||
backend->cogl_context = cogl_context_new (backend->cogl_display, &internal_error);
|
||||
if (backend->cogl_context == NULL)
|
||||
goto error;
|
||||
|
||||
@ -413,12 +446,19 @@ _clutter_create_backend (void)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_real_init_events (ClutterBackend *backend)
|
||||
{
|
||||
g_error ("Unknown input backend");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_class_init (ClutterBackendClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_backend_dispose;
|
||||
gobject_class->finalize = clutter_backend_finalize;
|
||||
|
||||
/**
|
||||
* ClutterBackend::resolution-changed:
|
||||
@ -474,6 +514,7 @@ clutter_backend_class_init (ClutterBackendClass *klass)
|
||||
klass->resolution_changed = clutter_backend_real_resolution_changed;
|
||||
klass->font_changed = clutter_backend_real_font_changed;
|
||||
|
||||
klass->init_events = clutter_backend_real_init_events;
|
||||
klass->create_context = clutter_backend_real_create_context;
|
||||
klass->get_features = clutter_backend_real_get_features;
|
||||
}
|
||||
@ -612,6 +653,17 @@ _clutter_backend_get_features (ClutterBackend *backend)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_init_events (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
g_assert (CLUTTER_IS_BACKEND (backend));
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
klass->init_events (backend);
|
||||
}
|
||||
|
||||
gfloat
|
||||
_clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||
PangoFontDescription *font_desc)
|
||||
@ -626,6 +678,31 @@ _clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||
return backend->units_per_em;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_copy_event_data (ClutterBackend *backend,
|
||||
const ClutterEvent *src,
|
||||
ClutterEvent *dest)
|
||||
{
|
||||
ClutterSeatClass *seat_class;
|
||||
ClutterSeat *seat;
|
||||
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
seat_class = CLUTTER_SEAT_GET_CLASS (seat);
|
||||
seat_class->copy_event_data (seat, src, dest);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_free_event_data (ClutterBackend *backend,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterSeatClass *seat_class;
|
||||
ClutterSeat *seat;
|
||||
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
seat_class = CLUTTER_SEAT_GET_CLASS (seat);
|
||||
seat_class->free_event_data (seat, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_get_default_backend:
|
||||
*
|
||||
@ -795,6 +872,31 @@ clutter_backend_get_cogl_context (ClutterBackend *backend)
|
||||
return backend->cogl_context;
|
||||
}
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
/**
|
||||
* clutter_wayland_set_compositor_display:
|
||||
* @display: A compositor side struct wl_display pointer
|
||||
*
|
||||
* This informs Clutter of your compositor side Wayland display
|
||||
* object. This must be called before calling clutter_init().
|
||||
*
|
||||
* Since: 1.8
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
clutter_wayland_set_compositor_display (void *display)
|
||||
{
|
||||
if (_clutter_context_is_initialized ())
|
||||
{
|
||||
g_warning ("%s() can only be used before calling clutter_init()",
|
||||
G_STRFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
_wayland_compositor_display = display;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
clutter_set_allowed_drivers (const char *drivers)
|
||||
{
|
||||
@ -875,10 +977,3 @@ clutter_backend_is_display_server (ClutterBackend *backend)
|
||||
{
|
||||
return CLUTTER_BACKEND_GET_CLASS (backend)->is_display_server (backend);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_backend_destroy (ClutterBackend *backend)
|
||||
{
|
||||
g_object_run_dispose (G_OBJECT (backend));
|
||||
g_object_unref (backend);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include <clutter/clutter-config.h>
|
||||
#include <clutter/clutter-keymap.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-seat.h>
|
||||
|
@ -59,7 +59,7 @@
|
||||
ClutterMargin *
|
||||
clutter_margin_new (void)
|
||||
{
|
||||
return g_new0 (ClutterMargin, 1);
|
||||
return g_slice_new0 (ClutterMargin);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,7 +77,7 @@ ClutterMargin *
|
||||
clutter_margin_copy (const ClutterMargin *margin_)
|
||||
{
|
||||
if (G_LIKELY (margin_ != NULL))
|
||||
return g_memdup2 (margin_, sizeof (ClutterMargin));
|
||||
return g_slice_dup (ClutterMargin, margin_);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -95,9 +95,198 @@ void
|
||||
clutter_margin_free (ClutterMargin *margin_)
|
||||
{
|
||||
if (G_LIKELY (margin_ != NULL))
|
||||
g_free (margin_);
|
||||
g_slice_free (ClutterMargin, margin_);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterMargin, clutter_margin,
|
||||
clutter_margin_copy,
|
||||
clutter_margin_free)
|
||||
|
||||
/**
|
||||
* ClutterMatrix:
|
||||
*
|
||||
* A type representing a 4x4 matrix.
|
||||
*
|
||||
* It is identicaly to #CoglMatrix.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
|
||||
static gpointer
|
||||
clutter_matrix_copy (gpointer data)
|
||||
{
|
||||
return cogl_matrix_copy (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_matrix_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
gdouble progress,
|
||||
GValue *retval)
|
||||
{
|
||||
const ClutterMatrix *matrix1 = g_value_get_boxed (a);
|
||||
const ClutterMatrix *matrix2 = g_value_get_boxed (b);
|
||||
graphene_point3d_t scale1 = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f);
|
||||
float shear1[3] = { 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t rotate1 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
graphene_point3d_t translate1 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
ClutterVertex4 perspective1 = { 0.f, 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t scale2 = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f);
|
||||
float shear2[3] = { 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t rotate2 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
graphene_point3d_t translate2 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
ClutterVertex4 perspective2 = { 0.f, 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t scale_res = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f);
|
||||
float shear_res = 0.f;
|
||||
graphene_point3d_t rotate_res = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
graphene_point3d_t translate_res = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
ClutterVertex4 perspective_res = { 0.f, 0.f, 0.f, 0.f };
|
||||
ClutterMatrix res;
|
||||
|
||||
clutter_matrix_init_identity (&res);
|
||||
|
||||
_clutter_util_matrix_decompose (matrix1,
|
||||
&scale1, shear1, &rotate1, &translate1,
|
||||
&perspective1);
|
||||
_clutter_util_matrix_decompose (matrix2,
|
||||
&scale2, shear2, &rotate2, &translate2,
|
||||
&perspective2);
|
||||
|
||||
/* perspective */
|
||||
_clutter_util_vertex4_interpolate (&perspective1, &perspective2, progress, &perspective_res);
|
||||
res.wx = perspective_res.x;
|
||||
res.wy = perspective_res.y;
|
||||
res.wz = perspective_res.z;
|
||||
res.ww = perspective_res.w;
|
||||
|
||||
/* translation */
|
||||
graphene_point3d_interpolate (&translate1, &translate2, progress, &translate_res);
|
||||
cogl_matrix_translate (&res, translate_res.x, translate_res.y, translate_res.z);
|
||||
|
||||
/* rotation */
|
||||
graphene_point3d_interpolate (&rotate1, &rotate2, progress, &rotate_res);
|
||||
cogl_matrix_rotate (&res, rotate_res.x, 1.0f, 0.0f, 0.0f);
|
||||
cogl_matrix_rotate (&res, rotate_res.y, 0.0f, 1.0f, 0.0f);
|
||||
cogl_matrix_rotate (&res, rotate_res.z, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
/* skew */
|
||||
shear_res = shear1[2] + (shear2[2] - shear1[2]) * progress; /* YZ */
|
||||
if (shear_res != 0.f)
|
||||
_clutter_util_matrix_skew_yz (&res, shear_res);
|
||||
|
||||
shear_res = shear1[1] + (shear2[1] - shear1[1]) * progress; /* XZ */
|
||||
if (shear_res != 0.f)
|
||||
_clutter_util_matrix_skew_xz (&res, shear_res);
|
||||
|
||||
shear_res = shear1[0] + (shear2[0] - shear1[0]) * progress; /* XY */
|
||||
if (shear_res != 0.f)
|
||||
_clutter_util_matrix_skew_xy (&res, shear_res);
|
||||
|
||||
/* scale */
|
||||
graphene_point3d_interpolate (&scale1, &scale2, progress, &scale_res);
|
||||
cogl_matrix_scale (&res, scale_res.x, scale_res.y, scale_res.z);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterMatrix, clutter_matrix,
|
||||
clutter_matrix_copy,
|
||||
clutter_matrix_free,
|
||||
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_matrix_progress))
|
||||
|
||||
/**
|
||||
* clutter_matrix_alloc:
|
||||
*
|
||||
* Allocates enough memory to hold a #ClutterMatrix.
|
||||
*
|
||||
* Return value: (transfer full): the newly allocated #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterMatrix, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_free:
|
||||
* @matrix: (allow-none): a #ClutterMatrix
|
||||
*
|
||||
* Frees the memory allocated by clutter_matrix_alloc().
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
void
|
||||
clutter_matrix_free (ClutterMatrix *matrix)
|
||||
{
|
||||
cogl_matrix_free (matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_init_identity:
|
||||
* @matrix: a #ClutterMatrix
|
||||
*
|
||||
* Initializes @matrix with the identity matrix, i.e.:
|
||||
*
|
||||
* |[
|
||||
* .xx = 1.0, .xy = 0.0, .xz = 0.0, .xw = 0.0
|
||||
* .yx = 0.0, .yy = 1.0, .yz = 0.0, .yw = 0.0
|
||||
* .zx = 0.0, .zy = 0.0, .zz = 1.0, .zw = 0.0
|
||||
* .wx = 0.0, .wy = 0.0, .wz = 0.0, .ww = 1.0
|
||||
* ]|
|
||||
*
|
||||
* Return value: (transfer none): the initialized #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_init_identity (ClutterMatrix *matrix)
|
||||
{
|
||||
cogl_matrix_init_identity (matrix);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_init_from_array:
|
||||
* @matrix: a #ClutterMatrix
|
||||
* @values: (array fixed-size=16): a C array of 16 floating point values,
|
||||
* representing a 4x4 matrix, with column-major order
|
||||
*
|
||||
* Initializes @matrix with the contents of a C array of floating point
|
||||
* values.
|
||||
*
|
||||
* Return value: (transfer none): the initialzed #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_init_from_array (ClutterMatrix *matrix,
|
||||
const float values[16])
|
||||
{
|
||||
cogl_matrix_init_from_array (matrix, values);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_init_from_matrix:
|
||||
* @a: the #ClutterMatrix to initialize
|
||||
* @b: the #ClutterMatrix to copy
|
||||
*
|
||||
* Initializes the #ClutterMatrix @a with the contents of the
|
||||
* #ClutterMatrix @b.
|
||||
*
|
||||
* Return value: (transfer none): the initialized #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_init_from_matrix (ClutterMatrix *a,
|
||||
const ClutterMatrix *b)
|
||||
{
|
||||
return memcpy (a, b, sizeof (ClutterMatrix));
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
#undef CBZ_L2T_INTERPOLATION
|
||||
|
||||
/****************************************************************************
|
||||
* ClutterBezier -- representation of a cubic bezier curve *
|
||||
* ClutterBezier -- represenation of a cubic bezier curve *
|
||||
* (private; a building block for the public bspline object) *
|
||||
****************************************************************************/
|
||||
|
||||
@ -104,7 +104,7 @@ struct _ClutterBezier
|
||||
ClutterBezier *
|
||||
_clutter_bezier_new (void)
|
||||
{
|
||||
return g_new0 (ClutterBezier, 1);
|
||||
return g_slice_new0 (ClutterBezier);
|
||||
}
|
||||
|
||||
void
|
||||
@ -112,7 +112,7 @@ _clutter_bezier_free (ClutterBezier * b)
|
||||
{
|
||||
if (G_LIKELY (b))
|
||||
{
|
||||
g_free (b);
|
||||
g_slice_free (ClutterBezier, b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ sqrti (int number)
|
||||
* algorithm does not calculate the square root, but its reciprocal ('y'
|
||||
* below), which is only at the end turned to the inverse value. In order
|
||||
* for the algorithm to produce satisfactory results, the reciprocal value
|
||||
* must be represented with sufficient precision; the 16.16 we use
|
||||
* must be represented with sufficient precission; the 16.16 we use
|
||||
* elsewhere in clutter is not good enough, and 10.22 is used instead.
|
||||
*/
|
||||
_FixedT x;
|
||||
@ -236,7 +236,7 @@ sqrti (int number)
|
||||
/* Now, we convert the float to 10.22 fixed. We exploit the mechanism
|
||||
* described at http://www.d6.com/users/checker/pdfs/gdmfp.pdf.
|
||||
*
|
||||
* We want 22 bit fraction; a single precision float uses 23 bit
|
||||
* We want 22 bit fraction; a single precission float uses 23 bit
|
||||
* mantisa, so we only need to add 2^(23-22) (no need for the 1.5
|
||||
* multiplier as we are only dealing with positive numbers).
|
||||
*
|
||||
@ -256,7 +256,7 @@ sqrti (int number)
|
||||
flt2.i = (flt2.i >> 11) * (y_1 >> 11);
|
||||
|
||||
/* If the original argument is less than 342, we do another
|
||||
* iteration to improve precision (for arguments >= 342, the single
|
||||
* iteration to improve precission (for arguments >= 342, the single
|
||||
* iteration produces generally better results).
|
||||
*/
|
||||
if (x < 171)
|
||||
|
@ -189,7 +189,7 @@ binding_entry_new (const gchar *name,
|
||||
|
||||
modifiers = modifiers & BINDING_MOD_MASK;
|
||||
|
||||
entry = g_new0 (ClutterBindingEntry, 1);
|
||||
entry = g_slice_new (ClutterBindingEntry);
|
||||
entry->key_val = key_val;
|
||||
entry->modifiers = modifiers;
|
||||
entry->name = (gchar *) g_intern_string (name);
|
||||
@ -221,7 +221,7 @@ binding_entry_free (gpointer data)
|
||||
|
||||
g_closure_unref (entry->closure);
|
||||
|
||||
g_free (entry);
|
||||
g_slice_free (ClutterBindingEntry, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-blur-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
@ -79,6 +81,9 @@ struct _ClutterBlurEffect
|
||||
|
||||
gint pixel_step_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
|
||||
@ -93,42 +98,20 @@ G_DEFINE_TYPE (ClutterBlurEffect,
|
||||
clutter_blur_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_blur_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterBlurEffect *blur_effect = CLUTTER_BLUR_EFFECT (effect);
|
||||
|
||||
if (blur_effect->pixel_step_uniform > -1)
|
||||
{
|
||||
float pixel_step[2];
|
||||
int tex_width, tex_height;
|
||||
|
||||
tex_width = cogl_texture_get_width (texture);
|
||||
tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
pixel_step[0] = 1.0f / tex_width;
|
||||
pixel_step[1] = 1.0f / tex_height;
|
||||
|
||||
cogl_pipeline_set_uniform_float (blur_effect->pipeline,
|
||||
blur_effect->pixel_step_uniform,
|
||||
2, /* n_components */
|
||||
1, /* count */
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (blur_effect->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (blur_effect->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_blur_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
if (self->actor == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* if we don't have support for GLSL shaders then we
|
||||
@ -142,7 +125,59 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class);
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
if (self->pixel_step_uniform > -1)
|
||||
{
|
||||
gfloat pixel_step[2];
|
||||
|
||||
pixel_step[0] = 1.0f / self->tex_width;
|
||||
pixel_step[1] = 1.0f / self->tex_height;
|
||||
|
||||
cogl_pipeline_set_uniform_float (self->pipeline,
|
||||
self->pixel_step_uniform,
|
||||
2, /* n_components */
|
||||
1, /* count */
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
guint8 paint_opacity;
|
||||
|
||||
paint_opacity = clutter_actor_get_paint_opacity (self->actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
self->tex_width, self->tex_height);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -194,7 +229,7 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass)
|
||||
effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_blur_effect_create_pipeline;
|
||||
offscreen_class->paint_target = clutter_blur_effect_paint_target;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1,431 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Endless OS Foundation, LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter-blur-private.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
|
||||
/**
|
||||
* SECTION:clutter-blur
|
||||
* @short_description: Blur textures
|
||||
*
|
||||
* #ClutterBlur is a moderately fast gaussian blur implementation.
|
||||
*
|
||||
* # Optimizations
|
||||
*
|
||||
* There are a number of optimizations in place to make this blur implementation
|
||||
* real-time. All in all, the implementation performs best when using large
|
||||
* blur-radii that allow downscaling the texture to smaller sizes, at small
|
||||
* radii where no downscaling is possible this can easily halve the framerate.
|
||||
*
|
||||
* ## Multipass
|
||||
*
|
||||
* It is implemented in 2 passes: vertical and horizontal.
|
||||
*
|
||||
* ## Downscaling
|
||||
*
|
||||
* #ClutterBlur uses dynamic downscaling to speed up blurring. Downscaling
|
||||
* happens in factors of 2 (the image is downscaled either by 2, 4, 8, 16, …)
|
||||
* and depends on the blur radius, the texture size, among others.
|
||||
*
|
||||
* The texture is drawn into a downscaled framebuffer; the blur passes are
|
||||
* applied on the downscaled texture contents; and finally, the blurred
|
||||
* contents are drawn
|
||||
* upscaled again.
|
||||
*
|
||||
* ## Hardware Interpolation
|
||||
*
|
||||
* This blur implementation cuts down the number of sampling operations by
|
||||
* exploiting the hardware interpolation that is performed when sampling between
|
||||
* pixel boundaries. This technique is described at:
|
||||
*
|
||||
* http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
|
||||
*
|
||||
* ## Incremental gauss-factor calculation
|
||||
*
|
||||
* The kernel values for the gaussian kernel are computed incrementally instead
|
||||
* of running the expensive calculations multiple times inside the blur shader.
|
||||
* The implementation is based on the algorithm presented by K. Turkowski in
|
||||
* GPU Gems 3, chapter 40:
|
||||
*
|
||||
* https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch40.html
|
||||
*
|
||||
*/
|
||||
|
||||
static const char *gaussian_blur_glsl_declarations =
|
||||
"uniform float sigma; \n"
|
||||
"uniform float pixel_step; \n"
|
||||
"uniform vec2 direction; \n";
|
||||
|
||||
static const char *gaussian_blur_glsl =
|
||||
" vec2 uv = vec2 (cogl_tex_coord.st); \n"
|
||||
" \n"
|
||||
" vec3 gauss_coefficient; \n"
|
||||
" gauss_coefficient.x = 1.0 / (sqrt (2.0 * 3.14159265) * sigma); \n"
|
||||
" gauss_coefficient.y = exp (-0.5 / (sigma * sigma)); \n"
|
||||
" gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y; \n"
|
||||
" \n"
|
||||
" float gauss_coefficient_total = gauss_coefficient.x; \n"
|
||||
" \n"
|
||||
" vec4 ret = texture2D (cogl_sampler, uv) * gauss_coefficient.x; \n"
|
||||
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
|
||||
" \n"
|
||||
" int n_steps = int (ceil (1.5 * sigma)) * 2; \n"
|
||||
" \n"
|
||||
" for (int i = 1; i <= n_steps; i += 2) { \n"
|
||||
" float coefficient_subtotal = gauss_coefficient.x; \n"
|
||||
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
|
||||
" coefficient_subtotal += gauss_coefficient.x; \n"
|
||||
" \n"
|
||||
" float gauss_ratio = gauss_coefficient.x / coefficient_subtotal; \n"
|
||||
" \n"
|
||||
" float foffset = float (i) + gauss_ratio; \n"
|
||||
" vec2 offset = direction * foffset * pixel_step; \n"
|
||||
" \n"
|
||||
" ret += texture2D (cogl_sampler, uv + offset) * coefficient_subtotal; \n"
|
||||
" ret += texture2D (cogl_sampler, uv - offset) * coefficient_subtotal; \n"
|
||||
" \n"
|
||||
" gauss_coefficient_total += 2.0 * coefficient_subtotal; \n"
|
||||
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" cogl_texel = ret / gauss_coefficient_total; \n";
|
||||
|
||||
#define MIN_DOWNSCALE_SIZE 256.f
|
||||
#define MAX_SIGMA 6.f
|
||||
|
||||
enum
|
||||
{
|
||||
VERTICAL,
|
||||
HORIZONTAL,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglPipeline *pipeline;
|
||||
CoglTexture *texture;
|
||||
int orientation;
|
||||
} BlurPass;
|
||||
|
||||
struct _ClutterBlur
|
||||
{
|
||||
CoglTexture *source_texture;
|
||||
float sigma;
|
||||
float downscale_factor;
|
||||
|
||||
BlurPass pass[2];
|
||||
};
|
||||
|
||||
static CoglPipeline*
|
||||
create_blur_pipeline (void)
|
||||
{
|
||||
static CoglPipelineKey blur_pipeline_key = "clutter-blur-pipeline-private";
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglPipeline *blur_pipeline;
|
||||
|
||||
blur_pipeline =
|
||||
cogl_context_get_named_pipeline (ctx, &blur_pipeline_key);
|
||||
|
||||
if (G_UNLIKELY (blur_pipeline == NULL))
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
|
||||
blur_pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_layer_null_texture (blur_pipeline, 0);
|
||||
cogl_pipeline_set_layer_filters (blur_pipeline,
|
||||
0,
|
||||
COGL_PIPELINE_FILTER_LINEAR,
|
||||
COGL_PIPELINE_FILTER_LINEAR);
|
||||
cogl_pipeline_set_layer_wrap_mode (blur_pipeline,
|
||||
0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
gaussian_blur_glsl_declarations,
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet, gaussian_blur_glsl);
|
||||
cogl_pipeline_add_layer_snippet (blur_pipeline, 0, snippet);
|
||||
cogl_object_unref (snippet);
|
||||
|
||||
cogl_context_set_named_pipeline (ctx, &blur_pipeline_key, blur_pipeline);
|
||||
}
|
||||
|
||||
return cogl_pipeline_copy (blur_pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
update_blur_uniforms (ClutterBlur *blur,
|
||||
BlurPass *pass)
|
||||
{
|
||||
gboolean vertical = pass->orientation == VERTICAL;
|
||||
int sigma_uniform;
|
||||
int pixel_step_uniform;
|
||||
int direction_uniform;
|
||||
|
||||
pixel_step_uniform =
|
||||
cogl_pipeline_get_uniform_location (pass->pipeline, "pixel_step");
|
||||
if (pixel_step_uniform > -1)
|
||||
{
|
||||
float pixel_step;
|
||||
|
||||
if (vertical)
|
||||
pixel_step = 1.f / cogl_texture_get_height (pass->texture);
|
||||
else
|
||||
pixel_step = 1.f / cogl_texture_get_width (pass->texture);
|
||||
|
||||
cogl_pipeline_set_uniform_1f (pass->pipeline,
|
||||
pixel_step_uniform,
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
sigma_uniform = cogl_pipeline_get_uniform_location (pass->pipeline, "sigma");
|
||||
if (sigma_uniform > -1)
|
||||
{
|
||||
cogl_pipeline_set_uniform_1f (pass->pipeline,
|
||||
sigma_uniform,
|
||||
blur->sigma / blur->downscale_factor);
|
||||
}
|
||||
|
||||
direction_uniform =
|
||||
cogl_pipeline_get_uniform_location (pass->pipeline, "direction");
|
||||
if (direction_uniform > -1)
|
||||
{
|
||||
gboolean horizontal = !vertical;
|
||||
float direction[2] = {
|
||||
horizontal,
|
||||
vertical,
|
||||
};
|
||||
|
||||
cogl_pipeline_set_uniform_float (pass->pipeline,
|
||||
direction_uniform,
|
||||
2, 1,
|
||||
direction);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_fbo (ClutterBlur *blur,
|
||||
BlurPass *pass)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
float scaled_height;
|
||||
float scaled_width;
|
||||
float height;
|
||||
float width;
|
||||
|
||||
g_clear_pointer (&pass->texture, cogl_object_unref);
|
||||
g_clear_object (&pass->framebuffer);
|
||||
|
||||
width = cogl_texture_get_width (blur->source_texture);
|
||||
height = cogl_texture_get_height (blur->source_texture);
|
||||
scaled_width = floorf (width / blur->downscale_factor);
|
||||
scaled_height = floorf (height / blur->downscale_factor);
|
||||
|
||||
pass->texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
|
||||
scaled_width,
|
||||
scaled_height));
|
||||
if (!pass->texture)
|
||||
return FALSE;
|
||||
|
||||
pass->framebuffer =
|
||||
COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (pass->texture));
|
||||
if (!pass->framebuffer)
|
||||
{
|
||||
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cogl_framebuffer_orthographic (pass->framebuffer,
|
||||
0.0, 0.0,
|
||||
scaled_width,
|
||||
scaled_height,
|
||||
0.0, 1.0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
setup_blur_pass (ClutterBlur *blur,
|
||||
BlurPass *pass,
|
||||
int orientation,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
pass->orientation = orientation;
|
||||
pass->pipeline = create_blur_pipeline ();
|
||||
cogl_pipeline_set_layer_texture (pass->pipeline, 0, texture);
|
||||
|
||||
if (!create_fbo (blur, pass))
|
||||
return FALSE;
|
||||
|
||||
update_blur_uniforms (blur, pass);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static float
|
||||
calculate_downscale_factor (float width,
|
||||
float height,
|
||||
float sigma)
|
||||
{
|
||||
float downscale_factor = 1.f;
|
||||
float scaled_width = width;
|
||||
float scaled_height = height;
|
||||
float scaled_sigma = sigma;
|
||||
|
||||
/* This is the algorithm used by Firefox; keep downscaling until either the
|
||||
* blur radius is lower than the threshold, or the downscaled texture is too
|
||||
* small.
|
||||
*/
|
||||
while (scaled_sigma > MAX_SIGMA &&
|
||||
scaled_width > MIN_DOWNSCALE_SIZE &&
|
||||
scaled_height > MIN_DOWNSCALE_SIZE)
|
||||
{
|
||||
downscale_factor *= 2.f;
|
||||
|
||||
scaled_width = width / downscale_factor;
|
||||
scaled_height = height / downscale_factor;
|
||||
scaled_sigma = sigma / downscale_factor;
|
||||
}
|
||||
|
||||
return downscale_factor;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_blur_pass (BlurPass *pass)
|
||||
{
|
||||
CoglColor transparent;
|
||||
|
||||
cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
|
||||
|
||||
cogl_framebuffer_clear (pass->framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR,
|
||||
&transparent);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (pass->framebuffer,
|
||||
pass->pipeline,
|
||||
0, 0,
|
||||
cogl_texture_get_width (pass->texture),
|
||||
cogl_texture_get_height (pass->texture));
|
||||
}
|
||||
|
||||
static void
|
||||
clear_blur_pass (BlurPass *pass)
|
||||
{
|
||||
g_clear_pointer (&pass->pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&pass->texture, cogl_object_unref);
|
||||
g_clear_object (&pass->framebuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_new:
|
||||
* @texture: a #CoglTexture
|
||||
* @sigma: blur sigma
|
||||
*
|
||||
* Creates a new #ClutterBlur.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): A newly created #ClutterBlur
|
||||
*/
|
||||
ClutterBlur *
|
||||
clutter_blur_new (CoglTexture *texture,
|
||||
float sigma)
|
||||
{
|
||||
ClutterBlur *blur;
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
BlurPass *hpass;
|
||||
BlurPass *vpass;
|
||||
|
||||
g_return_val_if_fail (texture != NULL, NULL);
|
||||
g_return_val_if_fail (sigma >= 0.0, NULL);
|
||||
|
||||
width = cogl_texture_get_width (texture);
|
||||
height = cogl_texture_get_height (texture);
|
||||
|
||||
blur = g_new0 (ClutterBlur, 1);
|
||||
blur->sigma = sigma;
|
||||
blur->source_texture = cogl_object_ref (texture);
|
||||
blur->downscale_factor = calculate_downscale_factor (width, height, sigma);
|
||||
|
||||
if (G_APPROX_VALUE (sigma, 0.0, FLT_EPSILON))
|
||||
goto out;
|
||||
|
||||
vpass = &blur->pass[VERTICAL];
|
||||
hpass = &blur->pass[HORIZONTAL];
|
||||
|
||||
if (!setup_blur_pass (blur, vpass, VERTICAL, texture) ||
|
||||
!setup_blur_pass (blur, hpass, HORIZONTAL, vpass->texture))
|
||||
{
|
||||
clutter_blur_free (blur);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
return g_steal_pointer (&blur);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_apply:
|
||||
* @blur: a #ClutterBlur
|
||||
*
|
||||
* Applies the blur. The resulting texture can be retrieved by
|
||||
* clutter_blur_get_texture().
|
||||
*/
|
||||
void
|
||||
clutter_blur_apply (ClutterBlur *blur)
|
||||
{
|
||||
if (G_APPROX_VALUE (blur->sigma, 0.0, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
apply_blur_pass (&blur->pass[VERTICAL]);
|
||||
apply_blur_pass (&blur->pass[HORIZONTAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_get_texture:
|
||||
* @blur: a #ClutterBlur
|
||||
*
|
||||
* Retrieves the texture where the blurred contents are stored. The
|
||||
* contents are undefined until clutter_blur_apply() is called.
|
||||
*
|
||||
* Returns: (transfer none): a #CoglTexture
|
||||
*/
|
||||
CoglTexture *
|
||||
clutter_blur_get_texture (ClutterBlur *blur)
|
||||
{
|
||||
if (G_APPROX_VALUE (blur->sigma, 0.0, FLT_EPSILON))
|
||||
return blur->source_texture;
|
||||
else
|
||||
return blur->pass[HORIZONTAL].texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_free:
|
||||
* @blur: A #ClutterBlur
|
||||
*
|
||||
* Frees @blur.
|
||||
*/
|
||||
void
|
||||
clutter_blur_free (ClutterBlur *blur)
|
||||
{
|
||||
g_assert (blur);
|
||||
|
||||
clear_blur_pass (&blur->pass[VERTICAL]);
|
||||
clear_blur_pass (&blur->pass[HORIZONTAL]);
|
||||
cogl_clear_object (&blur->source_texture);
|
||||
g_free (blur);
|
||||
}
|
@ -39,7 +39,7 @@
|
||||
* #ClutterActor:y-expand are set, the available size
|
||||
* - honours the #ClutterActor's #ClutterActor:x-align and #ClutterActor:y-align properties
|
||||
* to fill the available size
|
||||
* - if the #ClutterBoxLayout:homogeneous boolean property is set, then all widgets will
|
||||
* - if the #ClutterBoxLayout:homogeneous boolean propert is set, then all widgets will
|
||||
* get the same size, ignoring expand settings and the preferred sizes
|
||||
*
|
||||
* It is possible to control the spacing between children of a
|
||||
@ -719,7 +719,7 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
|
||||
|
||||
if (priv->is_homogeneous)
|
||||
{
|
||||
/* If were homogeneous we still need to run the above loop to get the
|
||||
/* If were homogenous we still need to run the above loop to get the
|
||||
* minimum sizes for children that are not going to fill
|
||||
*/
|
||||
if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL)
|
||||
@ -1218,7 +1218,7 @@ clutter_box_layout_get_homogeneous (ClutterBoxLayout *layout)
|
||||
* @pack_start: %TRUE if the @layout should pack children at the
|
||||
* beginning of the layout
|
||||
*
|
||||
* Sets whether children of @layout should be laid out by appending
|
||||
* Sets whether children of @layout should be layed out by appending
|
||||
* them or by prepending them
|
||||
*
|
||||
* Since: 1.2
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-brightness-contrast-effect.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
@ -67,6 +69,9 @@ struct _ClutterBrightnessContrastEffect
|
||||
gint brightness_offset_uniform;
|
||||
gint contrast_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
|
||||
@ -124,26 +129,16 @@ will_have_no_effect (ClutterBrightnessContrastEffect *self)
|
||||
G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON));
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_brightness_contrast_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self =
|
||||
CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (self->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (will_have_no_effect (self))
|
||||
return FALSE;
|
||||
|
||||
@ -162,8 +157,47 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
|
||||
|
||||
parent_class =
|
||||
CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterActor *actor;
|
||||
guint8 paint_opacity;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
self->tex_width, self->tex_height);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -263,7 +297,7 @@ clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectCl
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_brightness_contrast_effect_create_pipeline;
|
||||
offscreen_class->paint_target = clutter_brightness_contrast_effect_paint_target;
|
||||
|
||||
effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint;
|
||||
|
||||
|
@ -4,5 +4,11 @@
|
||||
/* List of Cogl drivers */
|
||||
#mesondefine CLUTTER_DRIVERS
|
||||
|
||||
/* Have evdev support for input handling */
|
||||
#mesondefine HAVE_EVDEV
|
||||
|
||||
/* Building with libwacom for advanced tablet management */
|
||||
#mesondefine HAVE_LIBWACOM
|
||||
|
||||
/* Supports PangoFt2 */
|
||||
#mesondefine HAVE_PANGO_FT2
|
||||
|
@ -50,6 +50,8 @@
|
||||
|
||||
#include "clutter-canvas.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-cairo.h"
|
||||
|
@ -114,7 +114,7 @@ struct _ClutterClickActionPrivate
|
||||
gint drag_threshold;
|
||||
|
||||
guint press_button;
|
||||
ClutterInputDevice *press_device;
|
||||
gint press_device_id;
|
||||
ClutterEventSequence *press_sequence;
|
||||
ClutterModifierType modifier_state;
|
||||
gfloat press_x;
|
||||
@ -272,23 +272,6 @@ click_action_cancel_long_press (ClutterClickAction *action)
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
event_within_drag_threshold (ClutterClickAction *click_action,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (click_action);
|
||||
float motion_x, motion_y;
|
||||
float delta_x, delta_y;
|
||||
|
||||
clutter_event_get_coords (event, &motion_x, &motion_y);
|
||||
|
||||
delta_x = ABS (motion_x - priv->press_x);
|
||||
delta_y = ABS (motion_y - priv->press_y);
|
||||
|
||||
return delta_x <= priv->drag_threshold && delta_y <= priv->drag_threshold;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
@ -316,7 +299,7 @@ on_event (ClutterActor *actor,
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
priv->press_button = has_button ? clutter_event_get_button (event) : 0;
|
||||
priv->press_device = clutter_event_get_device (event);
|
||||
priv->press_device_id = clutter_event_get_device_id (event);
|
||||
priv->press_sequence = clutter_event_get_event_sequence (event);
|
||||
priv->modifier_state = clutter_event_get_state (event);
|
||||
clutter_event_get_coords (event, &priv->press_x, &priv->press_y);
|
||||
@ -387,7 +370,7 @@ on_captured_event (ClutterActor *stage,
|
||||
|
||||
if ((has_button && clutter_event_get_button (event) != priv->press_button) ||
|
||||
(has_button && clutter_event_get_click_count (event) != 1) ||
|
||||
clutter_event_get_device (event) != priv->press_device ||
|
||||
clutter_event_get_device_id (event) != priv->press_device_id ||
|
||||
clutter_event_get_event_sequence (event) != priv->press_sequence)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
@ -419,23 +402,30 @@ on_captured_event (ClutterActor *stage,
|
||||
priv->modifier_state = 0;
|
||||
|
||||
click_action_set_pressed (action, FALSE);
|
||||
|
||||
if (event_within_drag_threshold (action, event))
|
||||
g_signal_emit (action, click_signals[CLICKED], 0, actor);
|
||||
g_signal_emit (action, click_signals[CLICKED], 0, actor);
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
{
|
||||
if (clutter_event_get_device (event) != priv->press_device ||
|
||||
gfloat motion_x, motion_y;
|
||||
gfloat delta_x, delta_y;
|
||||
|
||||
if (clutter_event_get_device_id (event) != priv->press_device_id ||
|
||||
clutter_event_get_event_sequence (event) != priv->press_sequence)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
if (!priv->is_held)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
if (!event_within_drag_threshold (action, event))
|
||||
clutter_click_action_release (action);
|
||||
clutter_event_get_coords (event, &motion_x, &motion_y);
|
||||
|
||||
delta_x = ABS (motion_x - priv->press_x);
|
||||
delta_y = ABS (motion_y - priv->press_y);
|
||||
|
||||
if (delta_x > priv->drag_threshold ||
|
||||
delta_y > priv->drag_threshold)
|
||||
click_action_cancel_long_press (action);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-clone.h"
|
||||
#include "clutter-debug.h"
|
||||
@ -120,17 +121,20 @@ clutter_clone_get_preferred_height (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_apply_transform (ClutterActor *self,
|
||||
graphene_matrix_t *matrix)
|
||||
clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
|
||||
{
|
||||
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
|
||||
|
||||
|
||||
if (priv->clone_source)
|
||||
graphene_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
|
||||
|
||||
/* First chain up and apply all the standard ClutterActor
|
||||
* transformations... */
|
||||
CLUTTER_ACTOR_CLASS (clutter_clone_parent_class)->apply_transform (self,
|
||||
matrix);
|
||||
|
||||
/* if we don't have a source, nothing else to do */
|
||||
if (priv->clone_source == NULL)
|
||||
return;
|
||||
|
||||
cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -195,7 +199,7 @@ clutter_clone_get_paint_volume (ClutterActor *actor,
|
||||
if (priv->clone_source == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* query the volume of the source actor and simply masquerade it as
|
||||
/* query the volume of the source actor and simply masquarade it as
|
||||
* the clones volume... */
|
||||
source_volume = clutter_actor_get_paint_volume (priv->clone_source);
|
||||
if (source_volume == NULL)
|
||||
|
@ -611,7 +611,7 @@ parse_hsla (ClutterColor *color,
|
||||
/**
|
||||
* clutter_color_from_string:
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
* @str: a string specifying a color
|
||||
* @str: a string specifiying a color
|
||||
*
|
||||
* Parses a string definition of a color, filling the #ClutterColor.red,
|
||||
* #ClutterColor.green, #ClutterColor.blue and #ClutterColor.alpha fields
|
||||
@ -911,7 +911,7 @@ ClutterColor *
|
||||
clutter_color_copy (const ClutterColor *color)
|
||||
{
|
||||
if (G_LIKELY (color != NULL))
|
||||
return g_memdup2 (color, sizeof (ClutterColor));
|
||||
return g_slice_dup (ClutterColor, color);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -928,7 +928,7 @@ void
|
||||
clutter_color_free (ClutterColor *color)
|
||||
{
|
||||
if (G_LIKELY (color != NULL))
|
||||
g_free (color);
|
||||
g_slice_free (ClutterColor, color);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -977,7 +977,7 @@ clutter_color_new (guint8 red,
|
||||
ClutterColor *
|
||||
clutter_color_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterColor, 1);
|
||||
return g_slice_new0 (ClutterColor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-colorize-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
@ -57,6 +59,9 @@ struct _ClutterColorizeEffect
|
||||
|
||||
gint tint_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
};
|
||||
|
||||
@ -99,24 +104,16 @@ G_DEFINE_TYPE (ClutterColorizeEffect,
|
||||
clutter_colorize_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_colorize_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterColorizeEffect *colorize_effect = CLUTTER_COLORIZE_EFFECT (effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (colorize_effect->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (colorize_effect->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_colorize_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* if we don't have support for GLSL shaders then we
|
||||
@ -130,7 +127,47 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class);
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterActor *actor;
|
||||
guint8 paint_opacity;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
self->tex_width, self->tex_height);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -196,7 +233,7 @@ clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass)
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_colorize_effect_create_pipeline;
|
||||
offscreen_class->paint_target = clutter_colorize_effect_paint_target;
|
||||
|
||||
effect_class->pre_paint = clutter_colorize_effect_pre_paint;
|
||||
|
||||
|
22
clutter/clutter/clutter-config.h.in
Normal file
22
clutter/clutter/clutter-config.h.in
Normal file
@ -0,0 +1,22 @@
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_CONFIG_H__
|
||||
#define __CLUTTER_CONFIG_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#mesondefine CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
#mesondefine CLUTTER_WINDOWING_X11
|
||||
#mesondefine CLUTTER_INPUT_X11
|
||||
#mesondefine CLUTTER_WINDOWING_GLX
|
||||
#mesondefine CLUTTER_WINDOWING_EGL
|
||||
#mesondefine CLUTTER_INPUT_EVDEV
|
||||
#mesondefine CLUTTER_INPUT_NULL
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_CONFIG_H__ */
|
@ -74,7 +74,7 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
|
||||
* fields in the instance and add the record to a data structure for
|
||||
* subsequent access for #ClutterContainerIface::get_child_meta
|
||||
* @destroy_child_meta: virtual function that gets called when a child is
|
||||
* removed; it should release all resources held by the record
|
||||
* removed; it shuld release all resources held by the record
|
||||
* @get_child_meta: return the record for a container child
|
||||
* @actor_added: class handler for #ClutterContainer::actor-added
|
||||
* @actor_removed: class handler for #ClutterContainer::actor-removed
|
||||
|
@ -22,28 +22,20 @@
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "clutter-macros.h"
|
||||
|
||||
typedef struct _ClutterDamageHistory ClutterDamageHistory;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterDamageHistory * clutter_damage_history_new (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_free (ClutterDamageHistory *history);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
|
||||
int age);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_record (ClutterDamageHistory *history,
|
||||
const cairo_region_t *damage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_step (ClutterDamageHistory *history);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
const cairo_region_t * clutter_damage_history_lookup (ClutterDamageHistory *history,
|
||||
int age);
|
||||
|
||||
|
@ -41,7 +41,6 @@ G_BEGIN_DECLS
|
||||
extern guint clutter_debug_flags;
|
||||
extern guint clutter_pick_debug_flags;
|
||||
extern guint clutter_paint_debug_flags;
|
||||
extern int clutter_max_render_time_constant_us;
|
||||
|
||||
void _clutter_debug_messagev (const char *format,
|
||||
va_list var_args) G_GNUC_PRINTF (1, 0);
|
||||
|
@ -53,16 +53,14 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#include "clutter-deform-effect.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-offscreen-effect-private.h"
|
||||
#include "clutter-paint-node.h"
|
||||
#include "clutter-paint-nodes.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#define DEFAULT_N_TILES 32
|
||||
@ -168,16 +166,19 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
|
||||
|
||||
static void
|
||||
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
|
||||
ClutterDeformEffectPrivate *priv = self->priv;
|
||||
CoglHandle material;
|
||||
CoglPipeline *pipeline;
|
||||
CoglDepthState depth_state;
|
||||
CoglFramebuffer *fb =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
if (priv->is_dirty)
|
||||
{
|
||||
graphene_rect_t rect;
|
||||
gboolean mapped_buffer;
|
||||
CoglVertexP3T2C4 *verts;
|
||||
ClutterActor *actor;
|
||||
@ -191,7 +192,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
/* if we don't have a target size, fall back to the actor's
|
||||
* allocation, though wrong it might be
|
||||
*/
|
||||
if (!clutter_offscreen_effect_get_target_size (effect, &width, &height))
|
||||
if (clutter_offscreen_effect_get_target_rect (effect, &rect))
|
||||
{
|
||||
width = graphene_rect_get_width (&rect);
|
||||
height = graphene_rect_get_height (&rect);
|
||||
}
|
||||
else
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
|
||||
/* XXX ideally, the sub-classes should tell us what they
|
||||
@ -271,7 +277,8 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
priv->is_dirty = FALSE;
|
||||
}
|
||||
|
||||
pipeline = clutter_offscreen_effect_get_pipeline (effect);
|
||||
material = clutter_offscreen_effect_get_target (effect);
|
||||
pipeline = COGL_PIPELINE (material);
|
||||
|
||||
/* enable depth testing */
|
||||
cogl_depth_state_init (&depth_state);
|
||||
@ -285,22 +292,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
COGL_PIPELINE_CULL_FACE_MODE_BACK);
|
||||
|
||||
/* draw the front */
|
||||
if (pipeline != NULL)
|
||||
{
|
||||
ClutterPaintNode *front_node;
|
||||
|
||||
front_node = clutter_pipeline_node_new (pipeline);
|
||||
clutter_paint_node_set_static_name (front_node,
|
||||
"ClutterDeformEffect (front)");
|
||||
clutter_paint_node_add_child (node, front_node);
|
||||
clutter_paint_node_add_primitive (front_node, priv->primitive);
|
||||
clutter_paint_node_unref (front_node);
|
||||
}
|
||||
if (material != NULL)
|
||||
cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);
|
||||
|
||||
/* draw the back */
|
||||
if (priv->back_pipeline != NULL)
|
||||
{
|
||||
ClutterPaintNode *back_node;
|
||||
CoglPipeline *back_pipeline;
|
||||
|
||||
/* We probably shouldn't be modifying the user's material so
|
||||
@ -310,30 +307,20 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
cogl_pipeline_set_cull_face_mode (back_pipeline,
|
||||
COGL_PIPELINE_CULL_FACE_MODE_FRONT);
|
||||
|
||||
cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);
|
||||
|
||||
back_node = clutter_pipeline_node_new (back_pipeline);
|
||||
clutter_paint_node_set_static_name (back_node,
|
||||
"ClutterDeformEffect (back)");
|
||||
clutter_paint_node_add_child (node, back_node);
|
||||
clutter_paint_node_add_primitive (back_node, priv->primitive);
|
||||
|
||||
clutter_paint_node_unref (back_node);
|
||||
cogl_object_unref (back_pipeline);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (priv->lines_primitive != NULL))
|
||||
{
|
||||
const ClutterColor *red;
|
||||
ClutterPaintNode *lines_node;
|
||||
|
||||
red = clutter_color_get_static (CLUTTER_COLOR_RED);
|
||||
|
||||
lines_node = clutter_color_node_new (red);
|
||||
clutter_paint_node_set_static_name (lines_node,
|
||||
"ClutterDeformEffect (lines)");
|
||||
clutter_paint_node_add_child (node, lines_node);
|
||||
clutter_paint_node_add_primitive (lines_node, priv->lines_primitive);
|
||||
clutter_paint_node_unref (lines_node);
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
|
||||
cogl_framebuffer_draw_primitive (fb, lines_pipeline,
|
||||
priv->lines_primitive);
|
||||
cogl_object_unref (lines_pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
* @see_also: #ClutterEffect, #ClutterOffscreenEffect
|
||||
*
|
||||
* #ClutterDesaturateEffect is a sub-class of #ClutterEffect that
|
||||
* desaturates the color of an actor and its contents. The strength
|
||||
* desaturates the color of an actor and its contents. The strenght
|
||||
* of the desaturation effect is controllable and animatable through
|
||||
* the #ClutterDesaturateEffect:factor property.
|
||||
*
|
||||
@ -41,6 +41,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter-desaturate-effect.h"
|
||||
@ -109,25 +111,16 @@ G_DEFINE_TYPE (ClutterDesaturateEffect,
|
||||
clutter_desaturate_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT);
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_desaturate_effect_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterDesaturateEffect *desaturate_effect =
|
||||
CLUTTER_DESATURATE_EFFECT (effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (desaturate_effect->pipeline, 0, texture);
|
||||
|
||||
return cogl_object_ref (desaturate_effect->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
|
||||
ClutterEffectClass *parent_class;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
|
||||
{
|
||||
/* if we don't have support for GLSL shaders then we
|
||||
@ -141,7 +134,52 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class);
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
if (parent_class->pre_paint (effect, paint_context))
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect =
|
||||
CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
CoglHandle texture;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
|
||||
self->tex_width = cogl_texture_get_width (texture);
|
||||
self->tex_height = cogl_texture_get_height (texture);
|
||||
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
ClutterActor *actor;
|
||||
CoglHandle texture;
|
||||
guint8 paint_opacity;
|
||||
|
||||
texture = clutter_offscreen_effect_get_texture (effect);
|
||||
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
cogl_pipeline_set_color4ub (self->pipeline,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
self->pipeline,
|
||||
0, 0,
|
||||
cogl_texture_get_width (texture),
|
||||
cogl_texture_get_height (texture));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -216,7 +254,7 @@ clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass)
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_desaturate_effect_create_pipeline;
|
||||
offscreen_class->paint_target = clutter_desaturate_effect_paint_target;
|
||||
|
||||
effect_class->pre_paint = clutter_desaturate_effect_pre_paint;
|
||||
|
||||
|
@ -5,11 +5,14 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean _clutter_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context);
|
||||
void _clutter_effect_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context);
|
||||
gboolean _clutter_effect_modify_paint_volume (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume);
|
||||
gboolean _clutter_effect_has_custom_paint_volume (ClutterEffect *effect);
|
||||
void _clutter_effect_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void _clutter_effect_pick (ClutterEffect *effect,
|
||||
|
@ -169,8 +169,6 @@
|
||||
#include "clutter-effect-private.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-paint-node-private.h"
|
||||
#include "clutter-paint-nodes.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-actor-private.h"
|
||||
|
||||
@ -180,7 +178,6 @@ G_DEFINE_ABSTRACT_TYPE (ClutterEffect,
|
||||
|
||||
static gboolean
|
||||
clutter_effect_real_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
return TRUE;
|
||||
@ -188,7 +185,6 @@ clutter_effect_real_pre_paint (ClutterEffect *effect,
|
||||
|
||||
static void
|
||||
clutter_effect_real_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
}
|
||||
@ -200,54 +196,26 @@ clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_actor_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node)
|
||||
{
|
||||
ClutterPaintNode *actor_node;
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
|
||||
actor_node = clutter_actor_node_new (actor, -1);
|
||||
clutter_paint_node_add_child (node, actor_node);
|
||||
clutter_paint_node_unref (actor_node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_real_paint_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
add_actor_node (effect, node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_real_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
||||
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
|
||||
ClutterActor *actor;
|
||||
gboolean pre_paint_succeeded;
|
||||
|
||||
/* The default implementation provides a compatibility wrapper for
|
||||
effects that haven't migrated to use the 'paint' virtual yet. This
|
||||
just calls the old pre and post virtuals before chaining on */
|
||||
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context);
|
||||
pre_paint_succeeded = _clutter_effect_pre_paint (effect, paint_context);
|
||||
|
||||
actor = clutter_actor_meta_get_actor (actor_meta);
|
||||
clutter_actor_continue_paint (actor, paint_context);
|
||||
|
||||
if (pre_paint_succeeded)
|
||||
{
|
||||
effect_class->paint_node (effect, node, paint_context, flags);
|
||||
effect_class->post_paint (effect, node, paint_context);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just paint the actor as fallback */
|
||||
add_actor_node (effect, node);
|
||||
}
|
||||
_clutter_effect_post_paint (effect, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -287,7 +255,6 @@ clutter_effect_class_init (ClutterEffectClass *klass)
|
||||
klass->post_paint = clutter_effect_real_post_paint;
|
||||
klass->modify_paint_volume = clutter_effect_real_modify_paint_volume;
|
||||
klass->paint = clutter_effect_real_paint;
|
||||
klass->paint_node = clutter_effect_real_paint_node;
|
||||
klass->pick = clutter_effect_real_pick;
|
||||
}
|
||||
|
||||
@ -296,18 +263,32 @@ clutter_effect_init (ClutterEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
||||
|
||||
return CLUTTER_EFFECT_GET_CLASS (effect)->pre_paint (effect, paint_context);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_effect_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->post_paint (effect, paint_context);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_effect_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect,
|
||||
node,
|
||||
paint_context,
|
||||
flags);
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->paint (effect, paint_context, flags);
|
||||
}
|
||||
|
||||
void
|
||||
@ -368,7 +349,7 @@ _clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
|
||||
* the actor itself so the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY would still
|
||||
* not be set. The effect can detect this case by keeping track of the
|
||||
* last modelview matrix that was used to render the actor and
|
||||
* verifying that it remains the same in the next paint.
|
||||
* veryifying that it remains the same in the next paint.
|
||||
*
|
||||
* Any other effects that are layered on top of the passed in effect
|
||||
* will still be passed the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag. If
|
||||
@ -392,6 +373,7 @@ clutter_effect_queue_repaint (ClutterEffect *effect)
|
||||
/* If the effect has no actor then nothing needs to be done */
|
||||
if (actor != NULL)
|
||||
_clutter_actor_queue_redraw_full (actor,
|
||||
0, /* flags */
|
||||
NULL, /* clip volume */
|
||||
effect /* effect */);
|
||||
}
|
||||
|
@ -77,21 +77,14 @@ struct _ClutterEffectClass
|
||||
|
||||
/*< public >*/
|
||||
gboolean (* pre_paint) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
void (* post_paint) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
gboolean (* modify_paint_volume) (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
void (* paint) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void (* paint_node) (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void (* pick) (ClutterEffect *effect,
|
||||
|
@ -14,9 +14,9 @@
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
{
|
||||
static size_t g_enum_type_id = 0;
|
||||
static volatile gsize g_enum_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_enum_type_id))
|
||||
if (g_once_init_enter (&g_enum_type_id__volatile))
|
||||
{
|
||||
static const G@Type@Value values[] = {
|
||||
/*** END value-header ***/
|
||||
@ -28,13 +28,14 @@ GType
|
||||
/*** BEGIN value-tail ***/
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType id;
|
||||
GType g_enum_type_id;
|
||||
|
||||
id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||
g_enum_type_id =
|
||||
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||
|
||||
g_once_init_leave (&g_enum_type_id, id);
|
||||
g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
|
||||
}
|
||||
|
||||
return g_enum_type_id;
|
||||
return g_enum_type_id__volatile;
|
||||
}
|
||||
/*** END value-tail ***/
|
||||
|
@ -127,7 +127,7 @@ typedef enum /*< prefix=CLUTTER_REQUEST >*/
|
||||
* @CLUTTER_EASE_IN_OUT_QUAD: quadratic tweening, combininig
|
||||
* %CLUTTER_EASE_IN_QUAD and %CLUTTER_EASE_OUT_QUAD
|
||||
* @CLUTTER_EASE_IN_CUBIC: cubic tweening
|
||||
* @CLUTTER_EASE_OUT_CUBIC: cubic tweening, inverse of
|
||||
* @CLUTTER_EASE_OUT_CUBIC: cubic tweening, invers of
|
||||
* %CLUTTER_EASE_IN_CUBIC
|
||||
* @CLUTTER_EASE_IN_OUT_CUBIC: cubic tweening, combining
|
||||
* %CLUTTER_EASE_IN_CUBIC and %CLUTTER_EASE_OUT_CUBIC
|
||||
@ -475,7 +475,7 @@ typedef enum {
|
||||
* a toplevel, and all parents visible)
|
||||
* @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been
|
||||
* allocated
|
||||
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emitting event
|
||||
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event
|
||||
* signals
|
||||
* @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program
|
||||
* @CLUTTER_ACTOR_NO_LAYOUT: the actor provides an explicit layout management
|
||||
@ -802,8 +802,7 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/
|
||||
CLUTTER_EVENT_NONE = 0,
|
||||
CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0,
|
||||
CLUTTER_EVENT_FLAG_INPUT_METHOD = 1 << 1,
|
||||
CLUTTER_EVENT_FLAG_REPEATED = 1 << 2,
|
||||
CLUTTER_EVENT_FLAG_RELATIVE_MOTION = 1 << 3,
|
||||
CLUTTER_EVENT_FLAG_REPEATED = 1 << 2
|
||||
} ClutterEventFlags;
|
||||
|
||||
/**
|
||||
@ -817,6 +816,9 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/
|
||||
* @CLUTTER_BUTTON_PRESS: Pointer button press event
|
||||
* @CLUTTER_BUTTON_RELEASE: Pointer button release event
|
||||
* @CLUTTER_SCROLL: Pointer scroll event
|
||||
* @CLUTTER_STAGE_STATE: Stage state change event
|
||||
* @CLUTTER_DESTROY_NOTIFY: Destroy notification event
|
||||
* @CLUTTER_CLIENT_MESSAGE: Client message event
|
||||
* @CLUTTER_TOUCH_BEGIN: A new touch event sequence has started;
|
||||
* event added in 1.10
|
||||
* @CLUTTER_TOUCH_UPDATE: A touch event sequence has been updated;
|
||||
@ -851,6 +853,9 @@ typedef enum /*< prefix=CLUTTER >*/
|
||||
CLUTTER_BUTTON_PRESS,
|
||||
CLUTTER_BUTTON_RELEASE,
|
||||
CLUTTER_SCROLL,
|
||||
CLUTTER_STAGE_STATE,
|
||||
CLUTTER_DESTROY_NOTIFY,
|
||||
CLUTTER_CLIENT_MESSAGE,
|
||||
CLUTTER_TOUCH_BEGIN,
|
||||
CLUTTER_TOUCH_UPDATE,
|
||||
CLUTTER_TOUCH_END,
|
||||
@ -865,9 +870,6 @@ typedef enum /*< prefix=CLUTTER >*/
|
||||
CLUTTER_PAD_RING,
|
||||
CLUTTER_DEVICE_ADDED,
|
||||
CLUTTER_DEVICE_REMOVED,
|
||||
CLUTTER_IM_COMMIT,
|
||||
CLUTTER_IM_DELETE,
|
||||
CLUTTER_IM_PREEDIT,
|
||||
|
||||
CLUTTER_EVENT_LAST /* helper */
|
||||
} ClutterEventType;
|
||||
@ -896,6 +898,19 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
|
||||
CLUTTER_SCROLL_SMOOTH
|
||||
} ClutterScrollDirection;
|
||||
|
||||
/**
|
||||
* ClutterStageState:
|
||||
* @CLUTTER_STAGE_STATE_ACTIVATED: Activated mask
|
||||
*
|
||||
* Stage state masks, used by the #ClutterEvent of type %CLUTTER_STAGE_STATE.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_STAGE_STATE_ACTIVATED = (1 << 3)
|
||||
} ClutterStageState;
|
||||
|
||||
/**
|
||||
* ClutterFeatureFlags:
|
||||
* @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer)
|
||||
@ -979,11 +994,11 @@ typedef enum
|
||||
|
||||
/**
|
||||
* ClutterInputMode:
|
||||
* @CLUTTER_INPUT_MODE_LOGICAL: A logical, virtual device
|
||||
* @CLUTTER_INPUT_MODE_PHYSICAL: A physical device, attached to
|
||||
* a logical device
|
||||
* @CLUTTER_INPUT_MODE_FLOATING: A physical device, not attached
|
||||
* to a logical device
|
||||
* @CLUTTER_INPUT_MODE_MASTER: A master, virtual device
|
||||
* @CLUTTER_INPUT_MODE_SLAVE: A slave, physical device, attached to
|
||||
* a master device
|
||||
* @CLUTTER_INPUT_MODE_FLOATING: A slave, physical device, not attached
|
||||
* to a master device
|
||||
*
|
||||
* The mode for input devices available.
|
||||
*
|
||||
@ -991,8 +1006,8 @@ typedef enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_MODE_LOGICAL,
|
||||
CLUTTER_INPUT_MODE_PHYSICAL,
|
||||
CLUTTER_INPUT_MODE_MASTER,
|
||||
CLUTTER_INPUT_MODE_SLAVE,
|
||||
CLUTTER_INPUT_MODE_FLOATING
|
||||
} ClutterInputMode;
|
||||
|
||||
@ -1032,20 +1047,6 @@ typedef enum
|
||||
CLUTTER_INPUT_AXIS_LAST
|
||||
} ClutterInputAxis;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_AXIS_FLAG_NONE = 0,
|
||||
CLUTTER_INPUT_AXIS_FLAG_X = 1 << CLUTTER_INPUT_AXIS_X,
|
||||
CLUTTER_INPUT_AXIS_FLAG_Y = 1 << CLUTTER_INPUT_AXIS_Y,
|
||||
CLUTTER_INPUT_AXIS_FLAG_PRESSURE = 1 << CLUTTER_INPUT_AXIS_PRESSURE,
|
||||
CLUTTER_INPUT_AXIS_FLAG_XTILT = 1 << CLUTTER_INPUT_AXIS_XTILT,
|
||||
CLUTTER_INPUT_AXIS_FLAG_YTILT = 1 << CLUTTER_INPUT_AXIS_YTILT,
|
||||
CLUTTER_INPUT_AXIS_FLAG_WHEEL = 1 << CLUTTER_INPUT_AXIS_WHEEL,
|
||||
CLUTTER_INPUT_AXIS_FLAG_DISTANCE = 1 << CLUTTER_INPUT_AXIS_DISTANCE,
|
||||
CLUTTER_INPUT_AXIS_FLAG_ROTATION = 1 << CLUTTER_INPUT_AXIS_ROTATION,
|
||||
CLUTTER_INPUT_AXIS_FLAG_SLIDER = 1 << CLUTTER_INPUT_AXIS_SLIDER,
|
||||
} ClutterInputAxisFlags;
|
||||
|
||||
/**
|
||||
* ClutterSnapEdge:
|
||||
* @CLUTTER_SNAP_EDGE_TOP: the top edge
|
||||
@ -1159,7 +1160,7 @@ typedef enum /*< prefix=CLUTTER_TEXTURE >*/
|
||||
*
|
||||
* Since: 0.8
|
||||
*
|
||||
* Deprecated: 1.22: The #ClutterTexture class was the only user of
|
||||
* Deprecated: 1.22: The #ClutterTexture class was the only used ot
|
||||
* this API; use #ClutterImage and clutter_actor_set_content_scaling_filters()
|
||||
* instead.
|
||||
*/
|
||||
@ -1593,13 +1594,6 @@ typedef enum
|
||||
CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER,
|
||||
} ClutterInputDevicePadSource;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_PAD_FEATURE_BUTTON,
|
||||
CLUTTER_PAD_FEATURE_RING,
|
||||
CLUTTER_PAD_FEATURE_STRIP,
|
||||
} ClutterInputDevicePadFeature;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_CONTENT_HINT_COMPLETION = 1 << 0,
|
||||
@ -1638,12 +1632,6 @@ typedef enum
|
||||
CLUTTER_INPUT_PANEL_STATE_TOGGLE,
|
||||
} ClutterInputPanelState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_PREEDIT_RESET_CLEAR,
|
||||
CLUTTER_PREEDIT_RESET_COMMIT,
|
||||
} ClutterPreeditResetMode;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ENUMS_H__ */
|
||||
|
@ -18,6 +18,7 @@ gboolean _clutter_event_process_filters (ClutterEvent *eve
|
||||
|
||||
/* clears the event queue inside the main context */
|
||||
void _clutter_clear_events_queue (void);
|
||||
void _clutter_clear_events_queue_for_stage (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_event_set_platform_data (ClutterEvent *event,
|
||||
|
@ -73,6 +73,8 @@ typedef struct _ClutterEventFilter {
|
||||
gpointer user_data;
|
||||
} ClutterEventFilter;
|
||||
|
||||
static GHashTable *all_events = NULL;
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterEvent, clutter_event,
|
||||
clutter_event_copy,
|
||||
clutter_event_free);
|
||||
@ -94,6 +96,15 @@ G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
|
||||
clutter_event_sequence_copy,
|
||||
clutter_event_sequence_free);
|
||||
|
||||
static gboolean
|
||||
is_event_allocated (const ClutterEvent *event)
|
||||
{
|
||||
if (all_events == NULL)
|
||||
return FALSE;
|
||||
|
||||
return g_hash_table_lookup (all_events, event) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_event_get_platform_data:
|
||||
* @event: a #ClutterEvent
|
||||
@ -107,6 +118,9 @@ G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
|
||||
gpointer
|
||||
_clutter_event_get_platform_data (const ClutterEvent *event)
|
||||
{
|
||||
if (!is_event_allocated (event))
|
||||
return NULL;
|
||||
|
||||
return ((ClutterEventPrivate *) event)->platform_data;
|
||||
}
|
||||
|
||||
@ -123,6 +137,9 @@ void
|
||||
_clutter_event_set_platform_data (ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
((ClutterEventPrivate *) event)->platform_data = data;
|
||||
}
|
||||
|
||||
@ -130,6 +147,9 @@ void
|
||||
_clutter_event_set_pointer_emulated (ClutterEvent *event,
|
||||
gboolean is_emulated)
|
||||
{
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
((ClutterEventPrivate *) event)->is_pointer_emulated = !!is_emulated;
|
||||
}
|
||||
|
||||
@ -384,6 +404,9 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
@ -393,9 +416,6 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
graphene_point_init (position, 0.f, 0.f);
|
||||
break;
|
||||
|
||||
@ -459,6 +479,9 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
@ -468,9 +491,6 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -697,6 +717,9 @@ clutter_event_set_scroll_delta (ClutterEvent *event,
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (event->type == CLUTTER_SCROLL);
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
|
||||
|
||||
((ClutterEventPrivate *) event)->delta_x = dx;
|
||||
@ -727,8 +750,13 @@ clutter_event_get_scroll_delta (const ClutterEvent *event,
|
||||
g_return_if_fail (event->type == CLUTTER_SCROLL);
|
||||
g_return_if_fail (event->scroll.direction == CLUTTER_SCROLL_SMOOTH);
|
||||
|
||||
delta_x = ((ClutterEventPrivate *) event)->delta_x;
|
||||
delta_y = ((ClutterEventPrivate *) event)->delta_y;
|
||||
delta_x = delta_y = 0;
|
||||
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
delta_x = ((ClutterEventPrivate *) event)->delta_x;
|
||||
delta_y = ((ClutterEventPrivate *) event)->delta_y;
|
||||
}
|
||||
|
||||
if (dx != NULL)
|
||||
*dx = delta_x;
|
||||
@ -1002,6 +1030,29 @@ clutter_event_get_event_sequence (const ClutterEvent *event)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_device_id:
|
||||
* @event: a clutter event
|
||||
*
|
||||
* Retrieves the events device id if set.
|
||||
*
|
||||
* Return value: A unique identifier for the device or -1 if the event has
|
||||
* no specific device set.
|
||||
*/
|
||||
gint
|
||||
clutter_event_get_device_id (const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = NULL;
|
||||
|
||||
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
return clutter_input_device_get_device_id (device);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_device_type:
|
||||
* @event: a #ClutterEvent
|
||||
@ -1040,20 +1091,23 @@ void
|
||||
clutter_event_set_device (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
g_set_object (&real_event->device, device);
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_set_object (&real_event->device, device);
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -1137,19 +1191,23 @@ ClutterInputDevice *
|
||||
clutter_event_get_device (const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = NULL;
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
if (real_event->device != NULL)
|
||||
return real_event->device;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
if (real_event->device != NULL)
|
||||
return real_event->device;
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
break;
|
||||
|
||||
@ -1228,11 +1286,14 @@ void
|
||||
clutter_event_set_device_tool (ClutterEvent *event,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
real_event->tool = tool;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
real_event->tool = tool;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1248,11 +1309,16 @@ clutter_event_set_device_tool (ClutterEvent *event,
|
||||
ClutterInputDeviceTool *
|
||||
clutter_event_get_device_tool (const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
return real_event->tool;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
return real_event->tool;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1269,11 +1335,16 @@ clutter_event_new (ClutterEventType type)
|
||||
ClutterEvent *new_event;
|
||||
ClutterEventPrivate *priv;
|
||||
|
||||
priv = g_new0 (ClutterEventPrivate, 1);
|
||||
priv = g_slice_new0 (ClutterEventPrivate);
|
||||
|
||||
new_event = (ClutterEvent *) priv;
|
||||
new_event->type = new_event->any.type = type;
|
||||
|
||||
if (G_UNLIKELY (all_events == NULL))
|
||||
all_events = g_hash_table_new (NULL, NULL);
|
||||
|
||||
g_hash_table_replace (all_events, priv, GUINT_TO_POINTER (1));
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
@ -1290,7 +1361,8 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
{
|
||||
ClutterEvent *new_event;
|
||||
ClutterEventPrivate *new_real_event;
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
ClutterInputDevice *device;
|
||||
gint n_axes = 0;
|
||||
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
@ -1299,45 +1371,45 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
|
||||
*new_event = *event;
|
||||
|
||||
g_set_object (&new_real_event->device, real_event->device);
|
||||
g_set_object (&new_real_event->source_device, real_event->source_device);
|
||||
new_real_event->delta_x = real_event->delta_x;
|
||||
new_real_event->delta_y = real_event->delta_y;
|
||||
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
||||
new_real_event->base_state = real_event->base_state;
|
||||
new_real_event->button_state = real_event->button_state;
|
||||
new_real_event->latched_state = real_event->latched_state;
|
||||
new_real_event->locked_state = real_event->locked_state;
|
||||
new_real_event->tool = real_event->tool;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_set_object (&new_real_event->device, real_event->device);
|
||||
g_set_object (&new_real_event->source_device, real_event->source_device);
|
||||
new_real_event->delta_x = real_event->delta_x;
|
||||
new_real_event->delta_y = real_event->delta_y;
|
||||
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
||||
new_real_event->base_state = real_event->base_state;
|
||||
new_real_event->button_state = real_event->button_state;
|
||||
new_real_event->latched_state = real_event->latched_state;
|
||||
new_real_event->locked_state = real_event->locked_state;
|
||||
new_real_event->tool = real_event->tool;
|
||||
}
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
n_axes = clutter_input_device_get_n_axes (device);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (event->button.axes != NULL)
|
||||
{
|
||||
new_event->button.axes =
|
||||
g_memdup2 (event->button.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->button.axes = g_memdup (event->button.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL:
|
||||
if (event->scroll.axes != NULL)
|
||||
{
|
||||
new_event->scroll.axes =
|
||||
g_memdup2 (event->scroll.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->scroll.axes = g_memdup (event->scroll.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
if (event->motion.axes != NULL)
|
||||
{
|
||||
new_event->motion.axes =
|
||||
g_memdup2 (event->motion.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->motion.axes = g_memdup (event->motion.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
@ -1345,26 +1417,21 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
case CLUTTER_TOUCH_END:
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
if (event->touch.axes != NULL)
|
||||
{
|
||||
new_event->touch.axes =
|
||||
g_memdup2 (event->touch.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->touch.axes = g_memdup (event->touch.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
new_event->device.device = event->device.device;
|
||||
break;
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
new_event->im.text = g_strdup (event->im.text);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_event_allocated (event))
|
||||
_clutter_backend_copy_event_data (clutter_get_default_backend (),
|
||||
event,
|
||||
new_event);
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
@ -1379,10 +1446,15 @@ clutter_event_free (ClutterEvent *event)
|
||||
{
|
||||
if (G_LIKELY (event != NULL))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
|
||||
|
||||
g_clear_object (&real_event->device);
|
||||
g_clear_object (&real_event->source_device);
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_clear_object (&real_event->device);
|
||||
g_clear_object (&real_event->source_device);
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
@ -1405,17 +1477,16 @@ clutter_event_free (ClutterEvent *event)
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
g_free (event->touch.axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
g_free (event->im.text);
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_free ((ClutterEventPrivate *) event);
|
||||
g_hash_table_remove (all_events, event);
|
||||
g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1440,6 +1511,12 @@ clutter_event_get (void)
|
||||
return event;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
spin_context (gpointer data)
|
||||
{
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_event_push (const ClutterEvent *event,
|
||||
gboolean do_copy)
|
||||
@ -1457,7 +1534,7 @@ _clutter_event_push (const ClutterEvent *event,
|
||||
}
|
||||
|
||||
g_async_queue_push (context->events_queue, (gpointer) event);
|
||||
g_main_context_wakeup (NULL);
|
||||
g_idle_add (spin_context, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1564,6 +1641,9 @@ clutter_event_get_source_device (const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventPrivate *real_event;
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return NULL;
|
||||
|
||||
real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
if (real_event->source_device != NULL)
|
||||
@ -1592,6 +1672,9 @@ clutter_event_set_source_device (ClutterEvent *event,
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
real_event = (ClutterEventPrivate *) event;
|
||||
g_set_object (&real_event->source_device, device);
|
||||
}
|
||||
@ -1612,10 +1695,14 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
guint *n_axes)
|
||||
{
|
||||
gdouble *retval = NULL;
|
||||
guint len = 0;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_ENTER:
|
||||
case CLUTTER_LEAVE:
|
||||
case CLUTTER_KEY_PRESS:
|
||||
@ -1653,14 +1740,22 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
len = clutter_input_device_get_n_axes (device);
|
||||
else
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
if (n_axes)
|
||||
*n_axes = CLUTTER_INPUT_AXIS_LAST;
|
||||
*n_axes = len;
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -1779,6 +1874,9 @@ clutter_event_is_pointer_emulated (const ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return FALSE;
|
||||
|
||||
return ((ClutterEventPrivate *) event)->is_pointer_emulated;
|
||||
}
|
||||
|
||||
@ -1830,7 +1928,7 @@ clutter_event_add_filter (ClutterStage *stage,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterEventFilter *event_filter = g_new0 (ClutterEventFilter, 1);
|
||||
ClutterEventFilter *event_filter = g_slice_new (ClutterEventFilter);
|
||||
static guint event_filter_id = 0;
|
||||
|
||||
event_filter->stage = stage;
|
||||
@ -1871,7 +1969,7 @@ clutter_event_remove_filter (guint id)
|
||||
event_filter->notify (event_filter->user_data);
|
||||
|
||||
context->event_filters = g_list_delete_link (context->event_filters, l);
|
||||
g_free (event_filter);
|
||||
g_slice_free (ClutterEventFilter, event_filter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2007,42 +2105,6 @@ clutter_event_get_gesture_motion_delta (const ClutterEvent *event,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_gesture_motion_delta_unaccelerated:
|
||||
* @event: A clutter touchpad gesture event
|
||||
* @dx: (out) (allow-none): the displacement relative to the pointer
|
||||
* position in the X axis, or %NULL
|
||||
* @dy: (out) (allow-none): the displacement relative to the pointer
|
||||
* position in the Y axis, or %NULL
|
||||
*
|
||||
* Returns the unaccelerated gesture motion deltas relative to the current
|
||||
* pointer position. Unlike clutter_event_get_gesture_motion_delta(),
|
||||
* pointer acceleration is ignored.
|
||||
**/
|
||||
void
|
||||
clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
|
||||
gdouble *dx,
|
||||
gdouble *dy)
|
||||
{
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
|
||||
event->type == CLUTTER_TOUCHPAD_SWIPE);
|
||||
|
||||
if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
||||
{
|
||||
if (dx)
|
||||
*dx = event->touchpad_pinch.dx_unaccel;
|
||||
if (dy)
|
||||
*dy = event->touchpad_pinch.dy_unaccel;
|
||||
}
|
||||
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
||||
{
|
||||
if (dx)
|
||||
*dx = event->touchpad_swipe.dx_unaccel;
|
||||
if (dy)
|
||||
*dy = event->touchpad_swipe.dy_unaccel;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* clutter_event_get_scroll_source:
|
||||
* @event: an scroll event
|
||||
@ -2163,58 +2225,3 @@ clutter_event_get_pad_event_details (const ClutterEvent *event,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
clutter_event_get_event_code (const ClutterEvent *event)
|
||||
{
|
||||
if (event->type == CLUTTER_KEY_PRESS ||
|
||||
event->type == CLUTTER_KEY_RELEASE)
|
||||
return event->key.evdev_code;
|
||||
else if (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_BUTTON_RELEASE)
|
||||
return event->button.evdev_code;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
clutter_event_sequence_get_slot (const ClutterEventSequence *sequence)
|
||||
{
|
||||
g_return_val_if_fail (sequence != NULL, -1);
|
||||
|
||||
return GPOINTER_TO_INT (sequence) - 1;
|
||||
}
|
||||
|
||||
int64_t
|
||||
clutter_event_get_time_us (const ClutterEvent *event)
|
||||
{
|
||||
if (event->type == CLUTTER_MOTION)
|
||||
return event->motion.time_us;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_event_get_relative_motion (const ClutterEvent *event,
|
||||
double *dx,
|
||||
double *dy,
|
||||
double *dx_unaccel,
|
||||
double *dy_unaccel)
|
||||
{
|
||||
if (event->type == CLUTTER_MOTION &&
|
||||
event->motion.flags & CLUTTER_EVENT_FLAG_RELATIVE_MOTION)
|
||||
{
|
||||
if (dx)
|
||||
*dx = event->motion.dx;
|
||||
if (dy)
|
||||
*dy = event->motion.dy;
|
||||
if (dx_unaccel)
|
||||
*dx_unaccel = event->motion.dx_unaccel;
|
||||
if (dy_unaccel)
|
||||
*dy_unaccel = event->motion.dy_unaccel;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ typedef struct _ClutterButtonEvent ClutterButtonEvent;
|
||||
typedef struct _ClutterKeyEvent ClutterKeyEvent;
|
||||
typedef struct _ClutterMotionEvent ClutterMotionEvent;
|
||||
typedef struct _ClutterScrollEvent ClutterScrollEvent;
|
||||
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
||||
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
||||
typedef struct _ClutterTouchEvent ClutterTouchEvent;
|
||||
typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent;
|
||||
@ -121,7 +122,6 @@ typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent;
|
||||
typedef struct _ClutterPadStripEvent ClutterPadStripEvent;
|
||||
typedef struct _ClutterPadRingEvent ClutterPadRingEvent;
|
||||
typedef struct _ClutterDeviceEvent ClutterDeviceEvent;
|
||||
typedef struct _ClutterIMEvent ClutterIMEvent;
|
||||
|
||||
/**
|
||||
* ClutterAnyEvent:
|
||||
@ -173,7 +173,6 @@ struct _ClutterKeyEvent
|
||||
guint keyval;
|
||||
guint16 hardware_keycode;
|
||||
gunichar unicode_value;
|
||||
uint32_t evdev_code;
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
@ -217,7 +216,6 @@ struct _ClutterButtonEvent
|
||||
guint click_count;
|
||||
gdouble *axes; /* Future use */
|
||||
ClutterInputDevice *device;
|
||||
uint32_t evdev_code;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -307,12 +305,6 @@ struct _ClutterMotionEvent
|
||||
ClutterModifierType modifier_state;
|
||||
gdouble *axes; /* Future use */
|
||||
ClutterInputDevice *device;
|
||||
|
||||
int64_t time_us;
|
||||
double dx;
|
||||
double dy;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -354,6 +346,32 @@ struct _ClutterScrollEvent
|
||||
ClutterScrollFinishFlags finish_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterStageStateEvent:
|
||||
* @type: event type
|
||||
* @time: event time
|
||||
* @flags: event flags
|
||||
* @stage: event source stage
|
||||
* @source: event source actor (unused)
|
||||
* @changed_mask: bitwise OR of the changed flags
|
||||
* @new_state: bitwise OR of the current state flags
|
||||
*
|
||||
* Event signalling a change in the #ClutterStage state.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
struct _ClutterStageStateEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source; /* XXX: should probably be the stage itself */
|
||||
|
||||
ClutterStageState changed_mask;
|
||||
ClutterStageState new_state;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterTouchEvent:
|
||||
* @type: event type
|
||||
@ -414,10 +432,6 @@ struct _ClutterTouchEvent
|
||||
* @y: the Y coordinate of the pointer, relative to the stage
|
||||
* @dx: movement delta of the pinch focal point in the X axis
|
||||
* @dy: movement delta of the pinch focal point in the Y axis
|
||||
* @dx_unaccel: unaccelerated movement delta of the pinch focal
|
||||
* point in the X axis
|
||||
* @dy_unaccel: unaccelerated movement delta of the pinch focal
|
||||
* point in the Y axis
|
||||
* @angle_delta: angle delta in degrees, clockwise rotations are
|
||||
* represented by positive deltas
|
||||
* @scale: the current scale
|
||||
@ -445,8 +459,6 @@ struct _ClutterTouchpadPinchEvent
|
||||
gfloat y;
|
||||
gfloat dx;
|
||||
gfloat dy;
|
||||
gfloat dx_unaccel;
|
||||
gfloat dy_unaccel;
|
||||
gfloat angle_delta;
|
||||
gfloat scale;
|
||||
guint n_fingers;
|
||||
@ -463,12 +475,8 @@ struct _ClutterTouchpadPinchEvent
|
||||
* @n_fingers: the number of fingers triggering the swipe
|
||||
* @x: the X coordinate of the pointer, relative to the stage
|
||||
* @y: the Y coordinate of the pointer, relative to the stage
|
||||
* @dx: movement delta of the swipe center point in the X axis
|
||||
* @dy: movement delta of the swipe center point in the Y axis
|
||||
* @dx_unaccel: unaccelerated movement delta of the swipe center
|
||||
* point in the X axis
|
||||
* @dy_unaccel: unaccelerated movement delta of the swipe center
|
||||
* point in the Y axis
|
||||
* @dx: movement delta of the pinch focal point in the X axis
|
||||
* @dy: movement delta of the pinch focal point in the Y axis
|
||||
*
|
||||
* Used for touchpad swipe gesture events. The current state of the
|
||||
* gesture will be determined by the @phase field.
|
||||
@ -489,8 +497,6 @@ struct _ClutterTouchpadSwipeEvent
|
||||
gfloat y;
|
||||
gfloat dx;
|
||||
gfloat dy;
|
||||
gfloat dx_unaccel;
|
||||
gfloat dy_unaccel;
|
||||
};
|
||||
|
||||
struct _ClutterPadButtonEvent
|
||||
@ -550,20 +556,6 @@ struct _ClutterDeviceEvent
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
struct _ClutterIMEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
uint32_t time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
char *text;
|
||||
int32_t offset;
|
||||
uint32_t len;
|
||||
ClutterPreeditResetMode mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterEvent:
|
||||
*
|
||||
@ -581,6 +573,7 @@ union _ClutterEvent
|
||||
ClutterKeyEvent key;
|
||||
ClutterMotionEvent motion;
|
||||
ClutterScrollEvent scroll;
|
||||
ClutterStageStateEvent stage_state;
|
||||
ClutterCrossingEvent crossing;
|
||||
ClutterTouchEvent touch;
|
||||
ClutterTouchpadPinchEvent touchpad_pinch;
|
||||
@ -590,7 +583,6 @@ union _ClutterEvent
|
||||
ClutterPadStripEvent pad_strip;
|
||||
ClutterPadRingEvent pad_ring;
|
||||
ClutterDeviceEvent device;
|
||||
ClutterIMEvent im;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -692,6 +684,8 @@ void clutter_event_set_stage (ClutterEvent
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * clutter_event_get_stage (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_event_get_device_id (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceType clutter_event_get_device_type (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_event_set_coords (ClutterEvent *event,
|
||||
@ -790,11 +784,6 @@ void clutter_event_get_gesture_motion_delta (const Clut
|
||||
gdouble *dx,
|
||||
gdouble *dy);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
|
||||
gdouble *dx,
|
||||
gdouble *dy);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event);
|
||||
|
||||
@ -809,20 +798,6 @@ gboolean clutter_event_get_pad_event_details (const Clut
|
||||
guint *number,
|
||||
guint *mode,
|
||||
gdouble *value);
|
||||
CLUTTER_EXPORT
|
||||
uint32_t clutter_event_get_event_code (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
int32_t clutter_event_sequence_get_slot (const ClutterEventSequence *sequence);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
int64_t clutter_event_get_time_us (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_event_get_relative_motion (const ClutterEvent *event,
|
||||
double *dx,
|
||||
double *dy,
|
||||
double *dx_unaccel,
|
||||
double *dy_unaccel);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -913,7 +913,7 @@ clutter_flow_layout_class_init (ClutterFlowLayoutClass *klass)
|
||||
* ClutterFlowLayout:orientation:
|
||||
*
|
||||
* The orientation of the #ClutterFlowLayout. The children
|
||||
* of the layout will be laid out following the orientation.
|
||||
* of the layout will be layed out following the orientation.
|
||||
*
|
||||
* This property also controls the overflowing directions
|
||||
*
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "clutter/clutter-frame-clock.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-main.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-timeline-private.h"
|
||||
@ -34,21 +33,8 @@ enum
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
/* An estimate queue holds several int64_t values. Adding a new value to the
|
||||
* queue overwrites the oldest value.
|
||||
*/
|
||||
#define ESTIMATE_QUEUE_LENGTH 16
|
||||
|
||||
typedef struct _EstimateQueue
|
||||
{
|
||||
int64_t values[ESTIMATE_QUEUE_LENGTH];
|
||||
int next_index;
|
||||
} EstimateQueue;
|
||||
|
||||
/* When heuristic render time is off,
|
||||
* wait 2ms after vblank before starting to draw next frame.
|
||||
*/
|
||||
#define SYNC_DELAY_FALLBACK_US ms2us (2)
|
||||
/* Wait 2ms after vblank before starting to draw next frame */
|
||||
#define SYNC_DELAY_US ms2us (2)
|
||||
|
||||
typedef struct _ClutterFrameListener
|
||||
{
|
||||
@ -77,7 +63,6 @@ struct _ClutterFrameClock
|
||||
GObject parent;
|
||||
|
||||
float refresh_rate;
|
||||
int64_t refresh_interval_us;
|
||||
ClutterFrameListener listener;
|
||||
|
||||
GSource *source;
|
||||
@ -85,29 +70,11 @@ struct _ClutterFrameClock
|
||||
int64_t frame_count;
|
||||
|
||||
ClutterFrameClockState state;
|
||||
int64_t last_dispatch_time_us;
|
||||
int64_t last_dispatch_lateness_us;
|
||||
int64_t last_presentation_time_us;
|
||||
|
||||
gboolean is_next_presentation_time_valid;
|
||||
int64_t next_presentation_time_us;
|
||||
|
||||
/* Buffer must be submitted to KMS and GPU rendering must be finished
|
||||
* this amount of time before the next presentation time.
|
||||
*/
|
||||
int64_t vblank_duration_us;
|
||||
/* Last KMS buffer submission time. */
|
||||
int64_t last_flip_time_us;
|
||||
|
||||
/* Last few durations between dispatch start and buffer swap. */
|
||||
EstimateQueue dispatch_to_swap_us;
|
||||
/* Last few durations between buffer swap and GPU rendering finish. */
|
||||
EstimateQueue swap_to_rendering_done_us;
|
||||
/* Last few durations between buffer swap and KMS submission. */
|
||||
EstimateQueue swap_to_flip_us;
|
||||
/* If we got new measurements last frame. */
|
||||
gboolean got_measurements_last_frame;
|
||||
|
||||
gboolean pending_reschedule;
|
||||
gboolean pending_reschedule_now;
|
||||
|
||||
@ -119,29 +86,12 @@ struct _ClutterFrameClock
|
||||
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
estimate_queue_add_value (EstimateQueue *queue,
|
||||
int64_t value)
|
||||
{
|
||||
queue->values[queue->next_index] = value;
|
||||
queue->next_index = (queue->next_index + 1) % ESTIMATE_QUEUE_LENGTH;
|
||||
}
|
||||
|
||||
float
|
||||
clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
return frame_clock->refresh_rate;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_frame_clock_set_refresh_rate (ClutterFrameClock *frame_clock,
|
||||
float refresh_rate)
|
||||
{
|
||||
frame_clock->refresh_rate = refresh_rate;
|
||||
frame_clock->refresh_interval_us =
|
||||
(int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
|
||||
ClutterTimeline *timeline)
|
||||
@ -231,44 +181,20 @@ void
|
||||
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
ClutterFrameInfo *frame_info)
|
||||
{
|
||||
frame_clock->last_presentation_time_us = frame_info->presentation_time;
|
||||
int64_t presentation_time_us = frame_info->presentation_time;
|
||||
|
||||
frame_clock->got_measurements_last_frame = FALSE;
|
||||
|
||||
if (frame_info->cpu_time_before_buffer_swap_us != 0 &&
|
||||
frame_info->gpu_rendering_duration_ns != 0)
|
||||
if (presentation_time_us > frame_clock->last_presentation_time_us ||
|
||||
((presentation_time_us - frame_clock->last_presentation_time_us) >
|
||||
INT64_MAX / 2))
|
||||
{
|
||||
int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us;
|
||||
|
||||
dispatch_to_swap_us =
|
||||
frame_info->cpu_time_before_buffer_swap_us -
|
||||
frame_clock->last_dispatch_time_us;
|
||||
swap_to_rendering_done_us =
|
||||
frame_info->gpu_rendering_duration_ns / 1000;
|
||||
swap_to_flip_us =
|
||||
frame_clock->last_flip_time_us -
|
||||
frame_info->cpu_time_before_buffer_swap_us;
|
||||
|
||||
CLUTTER_NOTE (FRAME_TIMINGS,
|
||||
"dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
|
||||
dispatch_to_swap_us,
|
||||
swap_to_rendering_done_us,
|
||||
swap_to_flip_us);
|
||||
|
||||
estimate_queue_add_value (&frame_clock->dispatch_to_swap_us,
|
||||
dispatch_to_swap_us);
|
||||
estimate_queue_add_value (&frame_clock->swap_to_rendering_done_us,
|
||||
swap_to_rendering_done_us);
|
||||
estimate_queue_add_value (&frame_clock->swap_to_flip_us,
|
||||
swap_to_flip_us);
|
||||
|
||||
frame_clock->got_measurements_last_frame = TRUE;
|
||||
frame_clock->last_presentation_time_us = presentation_time_us;
|
||||
}
|
||||
|
||||
if (frame_info->refresh_rate > 1)
|
||||
else
|
||||
{
|
||||
clutter_frame_clock_set_refresh_rate (frame_clock,
|
||||
frame_info->refresh_rate);
|
||||
g_warning_once ("Bogus presentation time %" G_GINT64_FORMAT
|
||||
" travelled back in time, using current time.",
|
||||
presentation_time_us);
|
||||
frame_clock->last_presentation_time_us = g_get_monotonic_time ();
|
||||
}
|
||||
|
||||
switch (frame_clock->state)
|
||||
@ -286,76 +212,6 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
g_warn_if_reached ();
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||
maybe_reschedule_update (frame_clock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t
|
||||
clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
int64_t refresh_interval_us;
|
||||
int64_t max_dispatch_to_swap_us = 0;
|
||||
int64_t max_swap_to_rendering_done_us = 0;
|
||||
int64_t max_swap_to_flip_us = 0;
|
||||
int64_t max_render_time_us;
|
||||
int i;
|
||||
|
||||
refresh_interval_us =
|
||||
(int64_t) (0.5 + G_USEC_PER_SEC / frame_clock->refresh_rate);
|
||||
|
||||
if (!frame_clock->got_measurements_last_frame ||
|
||||
G_UNLIKELY (clutter_paint_debug_flags &
|
||||
CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME))
|
||||
return refresh_interval_us - SYNC_DELAY_FALLBACK_US;
|
||||
|
||||
for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i)
|
||||
{
|
||||
max_dispatch_to_swap_us =
|
||||
MAX (max_dispatch_to_swap_us,
|
||||
frame_clock->dispatch_to_swap_us.values[i]);
|
||||
max_swap_to_rendering_done_us =
|
||||
MAX (max_swap_to_rendering_done_us,
|
||||
frame_clock->swap_to_rendering_done_us.values[i]);
|
||||
max_swap_to_flip_us =
|
||||
MAX (max_swap_to_flip_us,
|
||||
frame_clock->swap_to_flip_us.values[i]);
|
||||
}
|
||||
|
||||
/* Max render time shows how early the frame clock needs to be dispatched
|
||||
* to make it to the predicted next presentation time. It is composed of:
|
||||
* - An estimate of duration from dispatch start to buffer swap.
|
||||
* - Maximum between estimates of duration from buffer swap to GPU rendering
|
||||
* finish and duration from buffer swap to buffer submission to KMS. This
|
||||
* is because both of these things need to happen before the vblank, and
|
||||
* they are done in parallel.
|
||||
* - Duration of the vblank.
|
||||
* - A constant to account for variations in the above estimates.
|
||||
*/
|
||||
max_render_time_us =
|
||||
max_dispatch_to_swap_us +
|
||||
MAX (max_swap_to_rendering_done_us, max_swap_to_flip_us) +
|
||||
frame_clock->vblank_duration_us +
|
||||
clutter_max_render_time_constant_us;
|
||||
|
||||
max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us);
|
||||
|
||||
return max_render_time_us;
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
int64_t *out_next_update_time_us,
|
||||
@ -363,6 +219,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
{
|
||||
int64_t last_presentation_time_us;
|
||||
int64_t now_us;
|
||||
float refresh_rate;
|
||||
int64_t refresh_interval_us;
|
||||
int64_t min_render_time_allowed_us;
|
||||
int64_t max_render_time_allowed_us;
|
||||
@ -373,119 +230,36 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
|
||||
now_us = g_get_monotonic_time ();
|
||||
|
||||
refresh_interval_us = frame_clock->refresh_interval_us;
|
||||
|
||||
if (frame_clock->last_presentation_time_us == 0)
|
||||
{
|
||||
*out_next_update_time_us =
|
||||
frame_clock->last_dispatch_time_us ?
|
||||
((frame_clock->last_dispatch_time_us -
|
||||
frame_clock->last_dispatch_lateness_us) + refresh_interval_us) :
|
||||
now_us;
|
||||
|
||||
*out_next_presentation_time_us = 0;
|
||||
return;
|
||||
}
|
||||
refresh_rate = frame_clock->refresh_rate;
|
||||
refresh_interval_us = (int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
|
||||
|
||||
min_render_time_allowed_us = refresh_interval_us / 2;
|
||||
max_render_time_allowed_us =
|
||||
clutter_frame_clock_compute_max_render_time_us (frame_clock);
|
||||
max_render_time_allowed_us = refresh_interval_us - SYNC_DELAY_US;
|
||||
|
||||
if (min_render_time_allowed_us > max_render_time_allowed_us)
|
||||
min_render_time_allowed_us = max_render_time_allowed_us;
|
||||
|
||||
/*
|
||||
* The common case is that the next presentation happens 1 refresh interval
|
||||
* after the last presentation:
|
||||
*
|
||||
* last_presentation_time_us
|
||||
* / next_presentation_time_us
|
||||
* / /
|
||||
* / /
|
||||
* |--|--o----|-------|--> presentation times
|
||||
* | | \ |
|
||||
* | | now_us
|
||||
* | \______/
|
||||
* | refresh_interval_us
|
||||
* |
|
||||
* 0
|
||||
*
|
||||
*/
|
||||
last_presentation_time_us = frame_clock->last_presentation_time_us;
|
||||
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
|
||||
|
||||
/*
|
||||
* However, the last presentation could have happened more than a frame ago.
|
||||
* For example, due to idling (nothing on screen changed, so no need to
|
||||
* redraw) or due to frames missing deadlines (GPU busy with heavy rendering).
|
||||
* The following code adjusts next_presentation_time_us to be in the future,
|
||||
* but still aligned to display presentation times. Instead of
|
||||
* next presentation = last presentation + 1 * refresh interval, it will be
|
||||
* next presentation = last presentation + N * refresh interval.
|
||||
*/
|
||||
/* Skip ahead to get close to the actual next presentation time. */
|
||||
if (next_presentation_time_us < now_us)
|
||||
{
|
||||
int64_t presentation_phase_us;
|
||||
int64_t current_phase_us;
|
||||
int64_t current_refresh_interval_start_us;
|
||||
int64_t logical_clock_offset_us;
|
||||
int64_t logical_clock_phase_us;
|
||||
int64_t hw_clock_offset_us;
|
||||
|
||||
/*
|
||||
* Let's say we're just past next_presentation_time_us.
|
||||
*
|
||||
* First, we compute presentation_phase_us. Real presentation times don't
|
||||
* have to be exact multiples of refresh_interval_us and
|
||||
* presentation_phase_us represents this difference. Next, we compute
|
||||
* current phase and the refresh interval start corresponding to now_us.
|
||||
* Finally, add presentation_phase_us and a refresh interval to get the
|
||||
* next presentation after now_us.
|
||||
*
|
||||
* last_presentation_time_us
|
||||
* / next_presentation_time_us
|
||||
* / / now_us
|
||||
* / / / new next_presentation_time_us
|
||||
* |--|-------|---o---|-------|--> presentation times
|
||||
* | __|
|
||||
* | |presentation_phase_us
|
||||
* | |
|
||||
* | | now_us - presentation_phase_us
|
||||
* | | /
|
||||
* |-------|---o---|-------|-----> integer multiples of refresh_interval_us
|
||||
* | \__/
|
||||
* | |current_phase_us
|
||||
* | \
|
||||
* | current_refresh_interval_start_us
|
||||
* 0
|
||||
*
|
||||
*/
|
||||
logical_clock_offset_us = now_us % refresh_interval_us;
|
||||
logical_clock_phase_us = now_us - logical_clock_offset_us;
|
||||
hw_clock_offset_us = last_presentation_time_us % refresh_interval_us;
|
||||
|
||||
presentation_phase_us = last_presentation_time_us % refresh_interval_us;
|
||||
current_phase_us = (now_us - presentation_phase_us) % refresh_interval_us;
|
||||
current_refresh_interval_start_us =
|
||||
now_us - presentation_phase_us - current_phase_us;
|
||||
|
||||
next_presentation_time_us =
|
||||
current_refresh_interval_start_us +
|
||||
presentation_phase_us +
|
||||
refresh_interval_us;
|
||||
next_presentation_time_us = logical_clock_phase_us + hw_clock_offset_us;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip one interval if we got an early presented event.
|
||||
*
|
||||
* last frame this was last_presentation_time
|
||||
* / frame_clock->next_presentation_time_us
|
||||
* / /
|
||||
* |---|-o-----|-x----->
|
||||
* | \
|
||||
* \ next_presentation_time_us is thus right after the last one
|
||||
* but got an unexpected early presentation
|
||||
* \_/
|
||||
* time_since_last_next_presentation_time_us
|
||||
*
|
||||
*/
|
||||
/* Skip one interval if we got an early presented event. */
|
||||
last_next_presentation_time_us = frame_clock->next_presentation_time_us;
|
||||
time_since_last_next_presentation_time_us =
|
||||
next_presentation_time_us - last_next_presentation_time_us;
|
||||
next_presentation_time_us - last_next_presentation_time_us;
|
||||
if (frame_clock->is_next_presentation_time_valid &&
|
||||
time_since_last_next_presentation_time_us < (refresh_interval_us / 2))
|
||||
{
|
||||
@ -592,8 +366,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
||||
calculate_next_update_time_us (frame_clock,
|
||||
&next_update_time_us,
|
||||
&frame_clock->next_presentation_time_us);
|
||||
frame_clock->is_next_presentation_time_valid =
|
||||
(frame_clock->next_presentation_time_us != 0);
|
||||
frame_clock->is_next_presentation_time_valid = TRUE;
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
return;
|
||||
@ -615,21 +388,9 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
||||
{
|
||||
int64_t frame_count;
|
||||
ClutterFrameResult result;
|
||||
int64_t ideal_dispatch_time_us, lateness_us;
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockDispatch, "Frame Clock (dispatch)");
|
||||
COGL_TRACE_BEGIN_SCOPED (ClutterFrameCLockDispatch, "Frame Clock (dispatch)");
|
||||
|
||||
ideal_dispatch_time_us = (frame_clock->last_dispatch_time_us -
|
||||
frame_clock->last_dispatch_lateness_us) +
|
||||
frame_clock->refresh_interval_us;
|
||||
|
||||
lateness_us = time_us - ideal_dispatch_time_us;
|
||||
if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us)
|
||||
frame_clock->last_dispatch_lateness_us = 0;
|
||||
else
|
||||
frame_clock->last_dispatch_lateness_us = lateness_us;
|
||||
|
||||
frame_clock->last_dispatch_time_us = time_us;
|
||||
g_source_set_ready_time (frame_clock->source, -1);
|
||||
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
|
||||
@ -695,58 +456,6 @@ frame_clock_source_dispatch (GSource *source,
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
||||
int64_t flip_time_us)
|
||||
{
|
||||
frame_clock->last_flip_time_us = flip_time_us;
|
||||
}
|
||||
|
||||
GString *
|
||||
clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
int64_t max_dispatch_to_swap_us = 0;
|
||||
int64_t max_swap_to_rendering_done_us = 0;
|
||||
int64_t max_swap_to_flip_us = 0;
|
||||
int i;
|
||||
GString *string;
|
||||
|
||||
string = g_string_new (NULL);
|
||||
g_string_append_printf (string, "Max render time: %ld µs",
|
||||
clutter_frame_clock_compute_max_render_time_us (frame_clock));
|
||||
|
||||
if (frame_clock->got_measurements_last_frame)
|
||||
g_string_append_printf (string, " =");
|
||||
else
|
||||
g_string_append_printf (string, " (no measurements last frame)");
|
||||
|
||||
for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i)
|
||||
{
|
||||
max_dispatch_to_swap_us =
|
||||
MAX (max_dispatch_to_swap_us,
|
||||
frame_clock->dispatch_to_swap_us.values[i]);
|
||||
max_swap_to_rendering_done_us =
|
||||
MAX (max_swap_to_rendering_done_us,
|
||||
frame_clock->swap_to_rendering_done_us.values[i]);
|
||||
max_swap_to_flip_us =
|
||||
MAX (max_swap_to_flip_us,
|
||||
frame_clock->swap_to_flip_us.values[i]);
|
||||
}
|
||||
|
||||
g_string_append_printf (string, "\nVblank duration: %ld µs +",
|
||||
frame_clock->vblank_duration_us);
|
||||
g_string_append_printf (string, "\nDispatch to swap: %ld µs +",
|
||||
max_dispatch_to_swap_us);
|
||||
g_string_append_printf (string, "\nmax(Swap to rendering done: %ld µs,",
|
||||
max_swap_to_rendering_done_us);
|
||||
g_string_append_printf (string, "\nSwap to flip: %ld µs) +",
|
||||
max_swap_to_flip_us);
|
||||
g_string_append_printf (string, "\nConstant: %d µs",
|
||||
clutter_max_render_time_constant_us);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static GSourceFuncs frame_clock_source_funcs = {
|
||||
NULL,
|
||||
NULL,
|
||||
@ -776,7 +485,6 @@ init_frame_clock_source (ClutterFrameClock *frame_clock)
|
||||
|
||||
ClutterFrameClock *
|
||||
clutter_frame_clock_new (float refresh_rate,
|
||||
int64_t vblank_duration_us,
|
||||
const ClutterFrameListenerIface *iface,
|
||||
gpointer user_data)
|
||||
{
|
||||
@ -791,8 +499,7 @@ clutter_frame_clock_new (float refresh_rate,
|
||||
|
||||
init_frame_clock_source (frame_clock);
|
||||
|
||||
clutter_frame_clock_set_refresh_rate (frame_clock, refresh_rate);
|
||||
frame_clock->vblank_duration_us = vblank_duration_us;
|
||||
frame_clock->refresh_rate = refresh_rate;
|
||||
|
||||
return frame_clock;
|
||||
}
|
||||
|
@ -40,9 +40,6 @@ G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||
CLUTTER, FRAME_CLOCK,
|
||||
GObject)
|
||||
|
||||
/**
|
||||
* ClutterFrameListenerIface: (skip)
|
||||
*/
|
||||
typedef struct _ClutterFrameListenerIface
|
||||
{
|
||||
void (* before_frame) (ClutterFrameClock *frame_clock,
|
||||
@ -56,7 +53,6 @@ typedef struct _ClutterFrameListenerIface
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_frame_clock_new (float refresh_rate,
|
||||
int64_t vblank_duration_us,
|
||||
const ClutterFrameListenerIface *iface,
|
||||
gpointer user_data);
|
||||
|
||||
@ -67,9 +63,6 @@ CLUTTER_EXPORT
|
||||
void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
|
||||
|
||||
@ -91,9 +84,4 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
||||
CLUTTER_EXPORT
|
||||
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
|
||||
|
||||
void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
||||
int64_t flip_time_us);
|
||||
|
||||
GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock);
|
||||
|
||||
#endif /* CLUTTER_FRAME_CLOCK_H */
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_FRAME_PRIVATE_H
|
||||
#define CLUTTER_FRAME_PRIVATE_H
|
||||
|
||||
#include "clutter/clutter-frame.h"
|
||||
|
||||
struct _ClutterFrame
|
||||
{
|
||||
gboolean has_result;
|
||||
ClutterFrameResult result;
|
||||
};
|
||||
|
||||
#define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 })
|
||||
|
||||
ClutterFrameResult clutter_frame_get_result (ClutterFrame *frame);
|
||||
|
||||
#endif /* CLUTTER_FRAME_PRIVATE_H */
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter/clutter-frame-private.h"
|
||||
|
||||
ClutterFrameResult
|
||||
clutter_frame_get_result (ClutterFrame *frame)
|
||||
{
|
||||
g_return_val_if_fail (frame->has_result, CLUTTER_FRAME_RESULT_IDLE);
|
||||
|
||||
return frame->result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_frame_has_result (ClutterFrame *frame)
|
||||
{
|
||||
return frame->has_result;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_set_result (ClutterFrame *frame,
|
||||
ClutterFrameResult result)
|
||||
{
|
||||
g_warn_if_fail (!frame->has_result);
|
||||
|
||||
frame->result = result;
|
||||
frame->has_result = TRUE;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_FRAME_H
|
||||
#define CLUTTER_FRAME_H
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-frame-clock.h"
|
||||
|
||||
typedef struct _ClutterFrame ClutterFrame;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_set_result (ClutterFrame *frame,
|
||||
ClutterFrameResult result);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_frame_has_result (ClutterFrame *frame);
|
||||
|
||||
#endif /* CLUTTER_FRAME_H */
|
@ -416,10 +416,12 @@ stage_captured_event_cb (ClutterActor *stage,
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
gesture_update_motion_point (point, event);
|
||||
|
||||
if (!begin_gesture (action, actor))
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
{
|
||||
if ((point = gesture_find_point (action, event, &position)) != NULL)
|
||||
gesture_update_motion_point (point, event);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
if ((point = gesture_find_point (action, event, &position)) == NULL)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
@ -572,13 +574,8 @@ clutter_gesture_action_set_enabled (ClutterActorMeta *meta,
|
||||
ClutterGestureActionPrivate *priv =
|
||||
clutter_gesture_action_get_instance_private (gesture_action);
|
||||
|
||||
if (!is_enabled)
|
||||
{
|
||||
if (priv->in_gesture)
|
||||
cancel_gesture (gesture_action);
|
||||
else
|
||||
g_array_set_size (priv->points, 0);
|
||||
}
|
||||
if (!is_enabled && priv->in_gesture)
|
||||
cancel_gesture (gesture_action);
|
||||
|
||||
meta_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
|
@ -29,23 +29,6 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-types.h"
|
||||
|
||||
static gboolean
|
||||
graphene_matrix_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
double progress,
|
||||
GValue *retval)
|
||||
{
|
||||
const graphene_matrix_t *am = g_value_get_boxed (a);
|
||||
const graphene_matrix_t *bm = g_value_get_boxed (b);
|
||||
graphene_matrix_t res;
|
||||
|
||||
graphene_matrix_interpolate (am, bm, progress, &res);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
graphene_point_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
@ -117,8 +100,6 @@ graphene_size_progress (const GValue *a,
|
||||
void
|
||||
clutter_graphene_init (void)
|
||||
{
|
||||
clutter_interval_register_progress_func (GRAPHENE_TYPE_MATRIX,
|
||||
graphene_matrix_progress);
|
||||
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT,
|
||||
graphene_point_progress);
|
||||
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT3D,
|
||||
|
@ -44,7 +44,7 @@ _clutter_id_pool_new (guint initial_size)
|
||||
{
|
||||
ClutterIDPool *self;
|
||||
|
||||
self = g_new0 (ClutterIDPool, 1);
|
||||
self = g_slice_new (ClutterIDPool);
|
||||
|
||||
self->array = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (gpointer), initial_size);
|
||||
@ -59,7 +59,7 @@ _clutter_id_pool_free (ClutterIDPool *id_pool)
|
||||
|
||||
g_array_free (id_pool->array, TRUE);
|
||||
g_slist_free (id_pool->free_ids);
|
||||
g_free (id_pool);
|
||||
g_slice_free (ClutterIDPool, id_pool);
|
||||
}
|
||||
|
||||
guint32
|
||||
|
@ -38,6 +38,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-image.h"
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
|
@ -32,6 +32,35 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterAxisInfo
|
||||
{
|
||||
ClutterInputAxis axis;
|
||||
|
||||
double min_axis;
|
||||
double max_axis;
|
||||
|
||||
double min_value;
|
||||
double max_value;
|
||||
|
||||
double resolution;
|
||||
} ClutterAxisInfo;
|
||||
|
||||
typedef struct _ClutterKeyInfo
|
||||
{
|
||||
guint keyval;
|
||||
ClutterModifierType modifiers;
|
||||
} ClutterKeyInfo;
|
||||
|
||||
typedef struct _ClutterScrollInfo
|
||||
{
|
||||
guint axis_id;
|
||||
ClutterScrollDirection direction;
|
||||
double increment;
|
||||
|
||||
double last_value;
|
||||
guint last_value_valid : 1;
|
||||
} ClutterScrollInfo;
|
||||
|
||||
typedef struct _ClutterPtrA11yData
|
||||
{
|
||||
int n_btn_pressed;
|
||||
@ -53,6 +82,26 @@ struct _ClutterInputDevice
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
int id;
|
||||
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterInputMode device_mode;
|
||||
|
||||
char *device_name;
|
||||
|
||||
ClutterSeat *seat;
|
||||
|
||||
ClutterBackend *backend;
|
||||
|
||||
/* the associated device */
|
||||
ClutterInputDevice *associated;
|
||||
|
||||
GList *slaves;
|
||||
|
||||
/* the actor underneath the pointer */
|
||||
ClutterActor *cursor_actor;
|
||||
GHashTable *inv_touch_sequence_actors;
|
||||
|
||||
/* the actor that has a grab in place for the device */
|
||||
ClutterActor *pointer_grab_actor;
|
||||
ClutterActor *keyboard_grab_actor;
|
||||
@ -61,7 +110,13 @@ struct _ClutterInputDevice
|
||||
|
||||
/* the current click count */
|
||||
int click_count;
|
||||
|
||||
/* the current state */
|
||||
int current_button_number;
|
||||
ClutterModifierType current_state;
|
||||
|
||||
/* the current touch points targets */
|
||||
GHashTable *touch_sequence_actors;
|
||||
|
||||
/* the previous state, used for click count generation */
|
||||
int previous_x;
|
||||
@ -69,9 +124,103 @@ struct _ClutterInputDevice
|
||||
uint32_t previous_time;
|
||||
int previous_button_number;
|
||||
|
||||
GArray *axes;
|
||||
|
||||
guint n_keys;
|
||||
GArray *keys;
|
||||
|
||||
GArray *scroll_info;
|
||||
|
||||
char *vendor_id;
|
||||
char *product_id;
|
||||
char *node_path;
|
||||
|
||||
GPtrArray *tools;
|
||||
|
||||
int n_rings;
|
||||
int n_strips;
|
||||
int n_mode_groups;
|
||||
|
||||
guint has_cursor : 1;
|
||||
guint is_enabled : 1;
|
||||
|
||||
/* Accessiblity */
|
||||
ClutterVirtualInputDevice *accessibility_virtual_device;
|
||||
ClutterPtrA11yData *ptr_a11y_data;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_associated_device (ClutterInputDevice *device,
|
||||
ClutterInputDevice *associated);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_add_slave (ClutterInputDevice *master,
|
||||
ClutterInputDevice *slave);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_remove_slave (ClutterInputDevice *master,
|
||||
ClutterInputDevice *slave);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_update_from_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_update (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
ClutterStage *stage,
|
||||
gboolean emit_crossing,
|
||||
ClutterEvent *for_event);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_remove_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
|
||||
guint n_keys);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint keyval,
|
||||
ClutterModifierType modifiers);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
gdouble *axis_value);
|
||||
CLUTTER_EXPORT
|
||||
guint _clutter_input_device_add_axis (ClutterInputDevice *device,
|
||||
ClutterInputAxis axis,
|
||||
gdouble minimum,
|
||||
gdouble maximum,
|
||||
gdouble resolution);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_reset_axes (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_add_scroll_info (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
ClutterScrollDirection direction,
|
||||
gdouble increment);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_input_device_get_scroll_delta (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
ClutterScrollDirection *direction_p,
|
||||
gdouble *delta_p);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_reset_scroll_info (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_add_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceTool *
|
||||
clutter_input_device_lookup_tool (ClutterInputDevice *device,
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
|
||||
#endif /* CLUTTER_INPUT_DEVICE_PRIVATE_H */
|
||||
|
@ -33,7 +33,6 @@ struct _ClutterInputDeviceToolPrivate
|
||||
ClutterInputDeviceToolType type;
|
||||
guint64 serial;
|
||||
guint64 id;
|
||||
ClutterInputAxisFlags axes;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -42,7 +41,6 @@ enum
|
||||
PROP_TYPE,
|
||||
PROP_SERIAL,
|
||||
PROP_ID,
|
||||
PROP_AXES,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -72,9 +70,6 @@ clutter_input_device_tool_set_property (GObject *object,
|
||||
case PROP_ID:
|
||||
priv->id = g_value_get_uint64 (value);
|
||||
break;
|
||||
case PROP_AXES:
|
||||
priv->axes = g_value_get_flags (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -102,9 +97,6 @@ clutter_input_device_tool_get_property (GObject *object,
|
||||
case PROP_ID:
|
||||
g_value_set_uint64 (value, priv->id);
|
||||
break;
|
||||
case PROP_AXES:
|
||||
g_value_set_flags (value, priv->axes);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -137,13 +129,6 @@ clutter_input_device_tool_class_init (ClutterInputDeviceToolClass *klass)
|
||||
P_("Tool ID"),
|
||||
0, G_MAXUINT64, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
props[PROP_AXES] =
|
||||
g_param_spec_flags ("axes",
|
||||
P_("Axes"),
|
||||
P_("Axes"),
|
||||
CLUTTER_TYPE_INPUT_AXIS_FLAGS,
|
||||
CLUTTER_INPUT_AXIS_FLAG_NONE,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, props);
|
||||
}
|
||||
@ -219,15 +204,3 @@ clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool)
|
||||
|
||||
return priv->id;
|
||||
}
|
||||
|
||||
ClutterInputAxisFlags
|
||||
clutter_input_device_tool_get_axes (ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceToolPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0);
|
||||
|
||||
priv = clutter_input_device_tool_get_instance_private (tool);
|
||||
|
||||
return priv->axes;
|
||||
}
|
||||
|
@ -64,9 +64,6 @@ ClutterInputDeviceToolType clutter_input_device_tool_get_tool_type (ClutterInput
|
||||
CLUTTER_EXPORT
|
||||
guint64 clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputAxisFlags clutter_input_device_tool_get_axes (ClutterInputDeviceTool *tool);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_TOOL_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,10 +34,19 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef void (*ClutterEmitInputDeviceEvent) (ClutterEvent *event,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
struct _ClutterInputDeviceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* keycode_to_evdev) (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
void (* update_from_tool) (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
gboolean (* is_mode_switch_button) (ClutterInputDevice *device,
|
||||
guint group,
|
||||
guint button);
|
||||
@ -47,9 +56,10 @@ struct _ClutterInputDeviceClass
|
||||
gboolean (* is_grouped) (ClutterInputDevice *device,
|
||||
ClutterInputDevice *other_device);
|
||||
|
||||
int (* get_pad_feature_group) (ClutterInputDevice *device,
|
||||
ClutterInputDevicePadFeature feature,
|
||||
int n_feature);
|
||||
/* Keyboard accessbility */
|
||||
void (* process_kbd_a11y_event) (ClutterEvent *event,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEmitInputDeviceEvent emit_event_func);
|
||||
};
|
||||
|
||||
#define CLUTTER_TYPE_INPUT_DEVICE (clutter_input_device_get_type ())
|
||||
@ -72,7 +82,18 @@ GType clutter_input_device_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_coords (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *point);
|
||||
CLUTTER_EXPORT
|
||||
ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
@ -80,6 +101,30 @@ ClutterInputMode clutter_input_device_get_device_mode (ClutterInputDev
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_has_cursor (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_input_device_get_n_axes (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputAxis clutter_input_device_get_axis (ClutterInputDevice *device,
|
||||
guint index_);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_axis_value (ClutterInputDevice *device,
|
||||
gdouble *axes,
|
||||
ClutterInputAxis axis,
|
||||
gdouble *value);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_input_device_get_n_keys (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint *keyval,
|
||||
ClutterModifierType *modifiers);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDevice * clutter_input_device_get_associated_device (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_input_device_get_slave_devices (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_grab (ClutterInputDevice *device,
|
||||
ClutterActor *actor);
|
||||
@ -110,9 +155,6 @@ CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_n_strips (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_n_mode_groups (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
int clutter_input_device_get_n_buttons (ClutterInputDevice *device);
|
||||
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_group_n_modes (ClutterInputDevice *device,
|
||||
@ -135,11 +177,6 @@ gboolean clutter_input_device_is_grouped (ClutterInputDev
|
||||
CLUTTER_EXPORT
|
||||
ClutterSeat * clutter_input_device_get_seat (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
int clutter_input_device_get_pad_feature_group (ClutterInputDevice *device,
|
||||
ClutterInputDevicePadFeature feature,
|
||||
int n_feature);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
|
||||
|
@ -30,8 +30,6 @@ typedef struct _ClutterInputFocusPrivate ClutterInputFocusPrivate;
|
||||
struct _ClutterInputFocusPrivate
|
||||
{
|
||||
ClutterInputMethod *im;
|
||||
char *preedit;
|
||||
ClutterPreeditResetMode mode;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputFocus, clutter_input_focus, G_TYPE_OBJECT)
|
||||
@ -55,25 +53,9 @@ clutter_input_focus_real_focus_out (ClutterInputFocus *focus)
|
||||
priv->im = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_focus_finalize (GObject *object)
|
||||
{
|
||||
ClutterInputFocus *focus = CLUTTER_INPUT_FOCUS (object);
|
||||
ClutterInputFocusPrivate *priv =
|
||||
clutter_input_focus_get_instance_private (focus);
|
||||
|
||||
g_clear_pointer (&priv->preedit, g_free);
|
||||
|
||||
G_OBJECT_CLASS (clutter_input_focus_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_focus_class_init (ClutterInputFocusClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = clutter_input_focus_finalize;
|
||||
|
||||
klass->focus_in = clutter_input_focus_real_focus_in;
|
||||
klass->focus_out = clutter_input_focus_real_focus_out;
|
||||
}
|
||||
@ -103,16 +85,6 @@ clutter_input_focus_reset (ClutterInputFocus *focus)
|
||||
|
||||
priv = clutter_input_focus_get_instance_private (focus);
|
||||
|
||||
if (priv->preedit)
|
||||
{
|
||||
if (priv->mode == CLUTTER_PREEDIT_RESET_COMMIT)
|
||||
clutter_input_focus_commit (focus, priv->preedit);
|
||||
|
||||
clutter_input_focus_set_preedit_text (focus, NULL, 0);
|
||||
g_clear_pointer (&priv->preedit, g_free);
|
||||
}
|
||||
|
||||
priv->mode = CLUTTER_PREEDIT_RESET_CLEAR;
|
||||
clutter_input_method_reset (priv->im);
|
||||
}
|
||||
|
||||
@ -175,8 +147,8 @@ clutter_input_focus_set_content_purpose (ClutterInputFocus *focus,
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_input_focus_filter_event (ClutterInputFocus *focus,
|
||||
const ClutterEvent *event)
|
||||
clutter_input_focus_filter_key_event (ClutterInputFocus *focus,
|
||||
const ClutterKeyEvent *key)
|
||||
{
|
||||
ClutterInputFocusPrivate *priv;
|
||||
|
||||
@ -185,41 +157,7 @@ clutter_input_focus_filter_event (ClutterInputFocus *focus,
|
||||
|
||||
priv = clutter_input_focus_get_instance_private (focus);
|
||||
|
||||
if (event->type == CLUTTER_KEY_PRESS ||
|
||||
event->type == CLUTTER_KEY_RELEASE)
|
||||
{
|
||||
return clutter_input_method_filter_key_event (priv->im, &event->key);
|
||||
}
|
||||
else if (event->type == CLUTTER_IM_COMMIT)
|
||||
{
|
||||
clutter_input_focus_commit (focus, event->im.text);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_IM_DELETE)
|
||||
{
|
||||
clutter_input_focus_delete_surrounding (focus, event->im.offset,
|
||||
event->im.len);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_IM_PREEDIT)
|
||||
{
|
||||
g_clear_pointer (&priv->preedit, g_free);
|
||||
priv->preedit = g_strdup (event->im.text);
|
||||
priv->mode = event->im.mode;
|
||||
clutter_input_focus_set_preedit_text (focus, event->im.text,
|
||||
event->im.offset);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_TOUCH_BEGIN ||
|
||||
(event->type == CLUTTER_BUTTON_PRESS &&
|
||||
event->button.button == CLUTTER_BUTTON_PRIMARY))
|
||||
{
|
||||
clutter_input_focus_reset (focus);
|
||||
/* pointing events are not consumed by IMs */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return clutter_input_method_filter_key_event (priv->im, key);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -72,8 +72,8 @@ CLUTTER_EXPORT
|
||||
void clutter_input_focus_set_content_purpose (ClutterInputFocus *focus,
|
||||
ClutterInputContentPurpose purpose);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_focus_filter_event (ClutterInputFocus *focus,
|
||||
const ClutterEvent *event);
|
||||
gboolean clutter_input_focus_filter_key_event (ClutterInputFocus *focus,
|
||||
const ClutterKeyEvent *key);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
|
||||
gboolean can_show_preedit);
|
||||
|
@ -277,48 +277,17 @@ clutter_input_method_get_focus (ClutterInputMethod *im)
|
||||
return priv->focus;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_method_put_im_event (ClutterInputMethod *im,
|
||||
ClutterEventType event_type,
|
||||
const char *text,
|
||||
int32_t offset,
|
||||
uint32_t len,
|
||||
ClutterPreeditResetMode mode)
|
||||
{
|
||||
ClutterInputDevice *keyboard;
|
||||
ClutterSeat *seat;
|
||||
ClutterStageManager *stage_manager;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
keyboard = clutter_seat_get_keyboard (seat);
|
||||
stage_manager = clutter_stage_manager_get_default ();
|
||||
stage = clutter_stage_manager_get_default_stage (stage_manager);
|
||||
|
||||
event = clutter_event_new (event_type);
|
||||
event->im.text = g_strdup (text);
|
||||
event->im.offset = offset;
|
||||
event->im.len = len;
|
||||
event->im.mode = mode;
|
||||
clutter_event_set_device (event, keyboard);
|
||||
clutter_event_set_source_device (event, keyboard);
|
||||
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_INPUT_METHOD);
|
||||
|
||||
clutter_event_set_stage (event, stage);
|
||||
|
||||
clutter_event_put (event);
|
||||
clutter_event_free (event);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_method_commit (ClutterInputMethod *im,
|
||||
const gchar *text)
|
||||
{
|
||||
ClutterInputMethodPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
|
||||
|
||||
clutter_input_method_put_im_event (im, CLUTTER_IM_COMMIT, text, 0, 0,
|
||||
CLUTTER_PREEDIT_RESET_CLEAR);
|
||||
priv = clutter_input_method_get_instance_private (im);
|
||||
if (priv->focus)
|
||||
clutter_input_focus_commit (priv->focus, text);
|
||||
}
|
||||
|
||||
void
|
||||
@ -326,10 +295,13 @@ clutter_input_method_delete_surrounding (ClutterInputMethod *im,
|
||||
int offset,
|
||||
guint len)
|
||||
{
|
||||
ClutterInputMethodPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
|
||||
|
||||
clutter_input_method_put_im_event (im, CLUTTER_IM_DELETE, NULL, offset, len,
|
||||
CLUTTER_PREEDIT_RESET_CLEAR);
|
||||
priv = clutter_input_method_get_instance_private (im);
|
||||
if (priv->focus)
|
||||
clutter_input_focus_delete_surrounding (priv->focus, offset, len);
|
||||
}
|
||||
|
||||
void
|
||||
@ -353,15 +325,17 @@ clutter_input_method_request_surrounding (ClutterInputMethod *im)
|
||||
* Sets the preedit text on the current input focus.
|
||||
**/
|
||||
void
|
||||
clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
unsigned int cursor,
|
||||
ClutterPreeditResetMode mode)
|
||||
clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
guint cursor)
|
||||
{
|
||||
ClutterInputMethodPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
|
||||
|
||||
clutter_input_method_put_im_event (im, CLUTTER_IM_PREEDIT, preedit,
|
||||
cursor, 0, mode);
|
||||
priv = clutter_input_method_get_instance_private (im);
|
||||
if (priv->focus)
|
||||
clutter_input_focus_set_preedit_text (priv->focus, preedit, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -501,7 +475,6 @@ clutter_input_method_forward_key (ClutterInputMethod *im,
|
||||
event->key.modifier_state = state;
|
||||
event->key.keyval = keyval;
|
||||
event->key.hardware_keycode = keycode;
|
||||
event->key.evdev_code = keycode - 8;
|
||||
event->key.unicode_value = clutter_keysym_to_unicode (keyval);
|
||||
|
||||
clutter_event_set_device (event, keyboard);
|
||||
|
@ -74,10 +74,9 @@ CLUTTER_EXPORT
|
||||
void clutter_input_method_request_surrounding (ClutterInputMethod *im);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
unsigned int cursor,
|
||||
ClutterPreeditResetMode mode);
|
||||
void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
guint cursor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_method_notify_key_event (ClutterInputMethod *im,
|
||||
|
@ -36,9 +36,8 @@ static gboolean
|
||||
is_secondary_click_enabled (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return (settings.controls & CLUTTER_A11Y_SECONDARY_CLICK_ENABLED);
|
||||
}
|
||||
@ -47,9 +46,8 @@ static gboolean
|
||||
is_dwell_click_enabled (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return (settings.controls & CLUTTER_A11Y_DWELL_ENABLED);
|
||||
}
|
||||
@ -58,9 +56,8 @@ static unsigned int
|
||||
get_secondary_click_delay (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.secondary_click_delay;
|
||||
}
|
||||
@ -69,9 +66,8 @@ static unsigned int
|
||||
get_dwell_delay (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_delay;
|
||||
}
|
||||
@ -80,9 +76,8 @@ static unsigned int
|
||||
get_dwell_threshold (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_threshold;
|
||||
}
|
||||
@ -91,9 +86,8 @@ static ClutterPointerA11yDwellMode
|
||||
get_dwell_mode (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_mode;
|
||||
}
|
||||
@ -102,9 +96,8 @@ static ClutterPointerA11yDwellClickType
|
||||
get_dwell_click_type (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_click_type;
|
||||
}
|
||||
@ -114,9 +107,8 @@ get_dwell_click_type_for_direction (ClutterInputDevice *device,
|
||||
ClutterPointerA11yDwellDirection direction)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
if (direction == settings.dwell_gesture_single)
|
||||
return CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY;
|
||||
@ -171,12 +163,11 @@ static gboolean
|
||||
trigger_secondary_click (gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = data;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->secondary_click_triggered = TRUE;
|
||||
device->ptr_a11y_data->secondary_click_timer = 0;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
|
||||
@ -189,12 +180,11 @@ static void
|
||||
start_secondary_click_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
unsigned int delay = get_secondary_click_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->secondary_click_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_secondary_click, device);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-started",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
|
||||
@ -204,14 +194,12 @@ start_secondary_click_timeout (ClutterInputDevice *device)
|
||||
static void
|
||||
stop_secondary_click_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (device->ptr_a11y_data->secondary_click_timer)
|
||||
{
|
||||
g_clear_handle_id (&device->ptr_a11y_data->secondary_click_timer,
|
||||
g_source_remove);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
|
||||
@ -314,9 +302,8 @@ update_dwell_click_type (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterPointerA11yDwellClickType dwell_click_type;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
dwell_click_type = settings.dwell_click_type;
|
||||
switch (dwell_click_type)
|
||||
@ -341,9 +328,9 @@ update_dwell_click_type (ClutterInputDevice *device)
|
||||
if (dwell_click_type != settings.dwell_click_type)
|
||||
{
|
||||
settings.dwell_click_type = dwell_click_type;
|
||||
clutter_seat_set_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_set_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-dwell-click-type-changed",
|
||||
dwell_click_type);
|
||||
}
|
||||
@ -437,7 +424,6 @@ trigger_dwell_gesture (gpointer data)
|
||||
ClutterInputDevice *device = data;
|
||||
ClutterPointerA11yDwellDirection direction;
|
||||
unsigned int delay = get_dwell_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
restore_dwell_position (device);
|
||||
direction = get_dwell_direction (device);
|
||||
@ -449,7 +435,7 @@ trigger_dwell_gesture (gpointer data)
|
||||
device->ptr_a11y_data->dwell_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_clear_dwell_gesture, device);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE,
|
||||
@ -462,13 +448,12 @@ static void
|
||||
start_dwell_gesture_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
unsigned int delay = get_dwell_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->dwell_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_dwell_gesture, device);
|
||||
device->ptr_a11y_data->dwell_gesture_started = TRUE;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-started",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE,
|
||||
@ -479,11 +464,10 @@ static gboolean
|
||||
trigger_dwell_click (gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = data;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->dwell_timer = 0;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
|
||||
@ -509,12 +493,11 @@ static void
|
||||
start_dwell_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
unsigned int delay = get_dwell_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->dwell_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_dwell_click, device);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-started",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
|
||||
@ -524,14 +507,12 @@ start_dwell_timeout (ClutterInputDevice *device)
|
||||
static void
|
||||
stop_dwell_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (device->ptr_a11y_data->dwell_timer)
|
||||
{
|
||||
g_clear_handle_id (&device->ptr_a11y_data->dwell_timer, g_source_remove);
|
||||
device->ptr_a11y_data->dwell_gesture_started = FALSE;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
|
||||
@ -589,9 +570,8 @@ static gboolean
|
||||
is_device_core_pointer (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
core_pointer = clutter_seat_get_pointer (seat);
|
||||
core_pointer = clutter_seat_get_pointer (device->seat);
|
||||
if (core_pointer == NULL)
|
||||
return FALSE;
|
||||
|
||||
@ -601,13 +581,11 @@ is_device_core_pointer (ClutterInputDevice *device)
|
||||
void
|
||||
_clutter_input_pointer_a11y_add_device (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (!is_device_core_pointer (device))
|
||||
return;
|
||||
|
||||
device->accessibility_virtual_device =
|
||||
clutter_seat_create_virtual_device (seat,
|
||||
clutter_seat_create_virtual_device (device->seat,
|
||||
CLUTTER_POINTER_DEVICE);
|
||||
|
||||
device->ptr_a11y_data = g_new0 (ClutterPtrA11yData, 1);
|
||||
|
@ -1176,7 +1176,7 @@ clutter_interval_compute_value (ClutterInterval *interval,
|
||||
* g_object_set_property()
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the computed value,
|
||||
* or %NULL if the computation was not successful
|
||||
* or %NULL if the computation was not successfull
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_KEYMAP_PRIVATE_H
|
||||
#define CLUTTER_KEYMAP_PRIVATE_H
|
||||
|
||||
#include "clutter/clutter-keymap.h"
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_keymap_set_lock_modifier_state (ClutterKeymap *keymap,
|
||||
gboolean caps_lock_state,
|
||||
gboolean num_lock_state);
|
||||
|
||||
#endif /* CLUTTER_KEYMAP_PRIVATE_H */
|
@ -21,29 +21,10 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-keymap-private.h"
|
||||
#include "clutter-keymap.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_CAPS_LOCK_STATE,
|
||||
PROP_NUM_LOCK_STATE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[N_PROPS];
|
||||
|
||||
typedef struct _ClutterKeymapPrivate
|
||||
{
|
||||
gboolean caps_lock_state;
|
||||
gboolean num_lock_state;
|
||||
} ClutterKeymapPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterKeymap, clutter_keymap,
|
||||
G_TYPE_OBJECT)
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterKeymap, clutter_keymap, G_TYPE_OBJECT)
|
||||
|
||||
enum
|
||||
{
|
||||
@ -53,76 +34,9 @@ enum
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0, };
|
||||
|
||||
static void
|
||||
clutter_keymap_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterKeymap *keymap = CLUTTER_KEYMAP (object);
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CAPS_LOCK_STATE:
|
||||
g_value_set_boolean (value, priv->caps_lock_state);
|
||||
break;
|
||||
case PROP_NUM_LOCK_STATE:
|
||||
g_value_set_boolean (value, priv->num_lock_state);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_keymap_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterKeymap *keymap = CLUTTER_KEYMAP (object);
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CAPS_LOCK_STATE:
|
||||
priv->caps_lock_state = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_NUM_LOCK_STATE:
|
||||
priv->num_lock_state = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_keymap_class_init (ClutterKeymapClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = clutter_keymap_get_property;
|
||||
object_class->set_property = clutter_keymap_set_property;
|
||||
|
||||
obj_props[PROP_CAPS_LOCK_STATE] =
|
||||
g_param_spec_boolean ("caps-lock-state",
|
||||
"Caps lock state",
|
||||
"Caps lock state",
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_props[PROP_NUM_LOCK_STATE] =
|
||||
g_param_spec_boolean ("num-lock-state",
|
||||
"Num lock state",
|
||||
"Num lock state",
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new (I_("state-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
@ -140,17 +54,13 @@ clutter_keymap_init (ClutterKeymap *keymap)
|
||||
gboolean
|
||||
clutter_keymap_get_num_lock_state (ClutterKeymap *keymap)
|
||||
{
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
return priv->num_lock_state;
|
||||
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_num_lock_state (keymap);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_keymap_get_caps_lock_state (ClutterKeymap *keymap)
|
||||
{
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
return priv->caps_lock_state;
|
||||
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_caps_lock_state (keymap);
|
||||
}
|
||||
|
||||
PangoDirection
|
||||
@ -158,35 +68,3 @@ clutter_keymap_get_direction (ClutterKeymap *keymap)
|
||||
{
|
||||
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_direction (keymap);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_keymap_set_lock_modifier_state (ClutterKeymap *keymap,
|
||||
gboolean caps_lock_state,
|
||||
gboolean num_lock_state)
|
||||
{
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
if (priv->caps_lock_state == caps_lock_state &&
|
||||
priv->num_lock_state == num_lock_state)
|
||||
return;
|
||||
|
||||
if (priv->caps_lock_state != caps_lock_state)
|
||||
{
|
||||
priv->caps_lock_state = caps_lock_state;
|
||||
g_object_notify_by_pspec (G_OBJECT (keymap),
|
||||
obj_props[PROP_CAPS_LOCK_STATE]);
|
||||
}
|
||||
|
||||
if (priv->num_lock_state != num_lock_state)
|
||||
{
|
||||
priv->num_lock_state = num_lock_state;
|
||||
g_object_notify_by_pspec (G_OBJECT (keymap),
|
||||
obj_props[PROP_NUM_LOCK_STATE]);
|
||||
}
|
||||
|
||||
g_debug ("Locks state changed - Num: %s, Caps: %s",
|
||||
priv->num_lock_state ? "set" : "unset",
|
||||
priv->caps_lock_state ? "set" : "unset");
|
||||
|
||||
g_signal_emit (keymap, signals[STATE_CHANGED], 0);
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ struct _ClutterKeymapClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* get_num_lock_state) (ClutterKeymap *keymap);
|
||||
gboolean (* get_caps_lock_state) (ClutterKeymap *keymap);
|
||||
PangoDirection (* get_direction) (ClutterKeymap *keymap);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# Author : Simos Xenitellis <simos at gnome dot org>.
|
||||
# Author : Bastien Nocera <hadess@hadess.net>
|
||||
# Authos : Bastien Nocera <hadess@hadess.net>
|
||||
# Version : 1.2
|
||||
#
|
||||
# Notes : It downloads keysymdef.h from the Internet, if not found locally,
|
||||
|
@ -41,7 +41,7 @@
|
||||
* The implementation of a layout manager does not differ from the
|
||||
* implementation of the size requisition and allocation bits of
|
||||
* #ClutterActor, so you should read the relative documentation
|
||||
* for subclassing #ClutterActor.
|
||||
* forr subclassing #ClutterActor.
|
||||
*
|
||||
* The layout manager implementation can hold a back pointer to the
|
||||
* #ClutterContainer by implementing the #ClutterLayoutManagerClass.set_container()
|
||||
|
@ -84,7 +84,7 @@ struct _ClutterLayoutManager
|
||||
* in newly written code.
|
||||
* @end_animation: virtual function; override to end an animation started
|
||||
* by clutter_layout_manager_begin_animation(). This virtual function is
|
||||
* deprecated, and it should not be overridden in newly written code.
|
||||
* deprecated, and it should not be overriden in newly written code.
|
||||
* @get_animation_progress: virtual function; override to control the
|
||||
* progress of the animation of a #ClutterLayoutManager. This virtual
|
||||
* function is deprecated, and it should not be overridden in newly written
|
||||
|
@ -53,6 +53,7 @@
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-config.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-event-private.h"
|
||||
#include "clutter-feature.h"
|
||||
@ -64,7 +65,6 @@
|
||||
#include "clutter-paint-node-private.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-settings-private.h"
|
||||
#include "clutter-stage.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-backend-private.h"
|
||||
@ -94,11 +94,6 @@ guint clutter_debug_flags = 0;
|
||||
guint clutter_paint_debug_flags = 0;
|
||||
guint clutter_pick_debug_flags = 0;
|
||||
|
||||
/* A constant added to heuristic max render time to account for variations
|
||||
* in the estimates.
|
||||
*/
|
||||
int clutter_max_render_time_constant_us = 2000;
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
static const GDebugKey clutter_debug_keys[] = {
|
||||
{ "misc", CLUTTER_DEBUG_MISC },
|
||||
@ -116,8 +111,6 @@ static const GDebugKey clutter_debug_keys[] = {
|
||||
{ "layout", CLUTTER_DEBUG_LAYOUT },
|
||||
{ "clipping", CLUTTER_DEBUG_CLIPPING },
|
||||
{ "oob-transforms", CLUTTER_DEBUG_OOB_TRANSFORMS },
|
||||
{ "frame-timings", CLUTTER_DEBUG_FRAME_TIMINGS },
|
||||
{ "detailed-trace", CLUTTER_DEBUG_DETAILED_TRACE },
|
||||
};
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
@ -135,10 +128,201 @@ static const GDebugKey clutter_paint_debug_keys[] = {
|
||||
{ "continuous-redraw", CLUTTER_DEBUG_CONTINUOUS_REDRAW },
|
||||
{ "paint-deform-tiles", CLUTTER_DEBUG_PAINT_DEFORM_TILES },
|
||||
{ "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION },
|
||||
{ "disable-dynamic-max-render-time", CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME },
|
||||
{ "max-render-time", CLUTTER_DEBUG_PAINT_MAX_RENDER_TIME },
|
||||
};
|
||||
|
||||
#define ENVIRONMENT_GROUP "Environment"
|
||||
#define DEBUG_GROUP "Debug"
|
||||
|
||||
static void
|
||||
clutter_config_read_from_key_file (GKeyFile *keyfile)
|
||||
{
|
||||
GError *key_error = NULL;
|
||||
gboolean bool_value;
|
||||
gint int_value;
|
||||
gchar *str_value;
|
||||
|
||||
if (!g_key_file_has_group (keyfile, ENVIRONMENT_GROUP))
|
||||
return;
|
||||
|
||||
str_value =
|
||||
g_key_file_get_string (keyfile, ENVIRONMENT_GROUP,
|
||||
"Drivers",
|
||||
&key_error);
|
||||
if (key_error != NULL)
|
||||
g_clear_error (&key_error);
|
||||
else
|
||||
clutter_set_allowed_drivers (str_value);
|
||||
|
||||
g_free (str_value);
|
||||
|
||||
bool_value =
|
||||
g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP,
|
||||
"ShowFps",
|
||||
&key_error);
|
||||
|
||||
if (key_error != NULL)
|
||||
g_clear_error (&key_error);
|
||||
else
|
||||
clutter_show_fps = bool_value;
|
||||
|
||||
bool_value =
|
||||
g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP,
|
||||
"DisableMipmappedText",
|
||||
&key_error);
|
||||
|
||||
if (key_error != NULL)
|
||||
g_clear_error (&key_error);
|
||||
else
|
||||
clutter_disable_mipmap_text = bool_value;
|
||||
|
||||
bool_value =
|
||||
g_key_file_get_boolean (keyfile, ENVIRONMENT_GROUP,
|
||||
"EnableAccessibility",
|
||||
&key_error);
|
||||
|
||||
if (key_error != NULL)
|
||||
g_clear_error (&key_error);
|
||||
else
|
||||
clutter_enable_accessibility = bool_value;
|
||||
|
||||
int_value =
|
||||
g_key_file_get_integer (keyfile, ENVIRONMENT_GROUP,
|
||||
"DefaultFps",
|
||||
&key_error);
|
||||
|
||||
if (key_error != NULL)
|
||||
g_clear_error (&key_error);
|
||||
else
|
||||
clutter_default_fps = int_value;
|
||||
|
||||
str_value =
|
||||
g_key_file_get_string (keyfile, ENVIRONMENT_GROUP,
|
||||
"TextDirection",
|
||||
&key_error);
|
||||
|
||||
if (key_error != NULL)
|
||||
g_clear_error (&key_error);
|
||||
else
|
||||
{
|
||||
if (g_strcmp0 (str_value, "rtl") == 0)
|
||||
clutter_text_direction = CLUTTER_TEXT_DIRECTION_RTL;
|
||||
else
|
||||
clutter_text_direction = CLUTTER_TEXT_DIRECTION_LTR;
|
||||
}
|
||||
|
||||
g_free (str_value);
|
||||
}
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
static void
|
||||
clutter_debug_read_from_key_file (GKeyFile *keyfile)
|
||||
{
|
||||
GError *key_error = NULL;
|
||||
gchar *value;
|
||||
|
||||
if (!g_key_file_has_group (keyfile, DEBUG_GROUP))
|
||||
return;
|
||||
|
||||
value = g_key_file_get_value (keyfile, DEBUG_GROUP,
|
||||
"Debug",
|
||||
&key_error);
|
||||
if (key_error == NULL)
|
||||
{
|
||||
clutter_debug_flags |=
|
||||
g_parse_debug_string (value,
|
||||
clutter_debug_keys,
|
||||
G_N_ELEMENTS (clutter_debug_keys));
|
||||
}
|
||||
else
|
||||
g_clear_error (&key_error);
|
||||
|
||||
g_free (value);
|
||||
|
||||
value = g_key_file_get_value (keyfile, DEBUG_GROUP,
|
||||
"PaintDebug",
|
||||
&key_error);
|
||||
if (key_error == NULL)
|
||||
{
|
||||
clutter_paint_debug_flags |=
|
||||
g_parse_debug_string (value,
|
||||
clutter_paint_debug_keys,
|
||||
G_N_ELEMENTS (clutter_paint_debug_keys));
|
||||
}
|
||||
else
|
||||
g_clear_error (&key_error);
|
||||
|
||||
g_free (value);
|
||||
|
||||
value = g_key_file_get_value (keyfile, DEBUG_GROUP,
|
||||
"PickDebug",
|
||||
&key_error);
|
||||
if (key_error == NULL)
|
||||
{
|
||||
clutter_pick_debug_flags |=
|
||||
g_parse_debug_string (value,
|
||||
clutter_pick_debug_keys,
|
||||
G_N_ELEMENTS (clutter_pick_debug_keys));
|
||||
}
|
||||
else
|
||||
g_clear_error (&key_error);
|
||||
|
||||
g_free (value);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
clutter_config_read_from_file (const gchar *config_path)
|
||||
{
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
GKeyFile *key_file = g_key_file_new ();
|
||||
GError *error = NULL;
|
||||
|
||||
g_key_file_load_from_file (key_file, config_path, G_KEY_FILE_NONE, &error);
|
||||
if (error == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "Reading configuration from '%s'", config_path);
|
||||
|
||||
clutter_config_read_from_key_file (key_file);
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
clutter_debug_read_from_key_file (key_file);
|
||||
#endif
|
||||
_clutter_settings_read_from_key_file (settings, key_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Unable to read configuration settings from '%s': %s",
|
||||
config_path,
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_key_file_free (key_file);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_config_read (void)
|
||||
{
|
||||
gchar *config_path;
|
||||
|
||||
config_path = g_build_filename (CLUTTER_SYSCONFDIR,
|
||||
"clutter-1.0",
|
||||
"settings.ini",
|
||||
NULL);
|
||||
if (g_file_test (config_path, G_FILE_TEST_EXISTS))
|
||||
clutter_config_read_from_file (config_path);
|
||||
|
||||
g_free (config_path);
|
||||
|
||||
config_path = g_build_filename (g_get_user_config_dir (),
|
||||
"clutter-1.0",
|
||||
"settings.ini",
|
||||
NULL);
|
||||
if (g_file_test (config_path, G_FILE_TEST_EXISTS))
|
||||
clutter_config_read_from_file (config_path);
|
||||
|
||||
g_free (config_path);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_context_get_show_fps (void)
|
||||
{
|
||||
@ -271,7 +455,7 @@ _clutter_threads_dispatch_free (gpointer data)
|
||||
if (dispatch->notify)
|
||||
dispatch->notify (dispatch->data);
|
||||
|
||||
g_free (dispatch);
|
||||
g_slice_free (ClutterThreadsDispatch, dispatch);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -371,7 +555,7 @@ clutter_threads_add_idle_full (gint priority,
|
||||
|
||||
g_return_val_if_fail (func != NULL, 0);
|
||||
|
||||
dispatch = g_new0 (ClutterThreadsDispatch, 1);
|
||||
dispatch = g_slice_new (ClutterThreadsDispatch);
|
||||
dispatch->func = func;
|
||||
dispatch->data = data;
|
||||
dispatch->notify = notify;
|
||||
@ -442,7 +626,7 @@ clutter_threads_add_timeout_full (gint priority,
|
||||
|
||||
g_return_val_if_fail (func != NULL, 0);
|
||||
|
||||
dispatch = g_new0 (ClutterThreadsDispatch, 1);
|
||||
dispatch = g_slice_new (ClutterThreadsDispatch);
|
||||
dispatch->func = func;
|
||||
dispatch->data = data;
|
||||
dispatch->notify = notify;
|
||||
@ -494,6 +678,12 @@ _clutter_context_get_default (void)
|
||||
{
|
||||
ClutterMainContext *ctx;
|
||||
|
||||
/* Read the configuration file, if any, before we set up the
|
||||
* whole thing, so that we can override things like the backend
|
||||
* and the driver
|
||||
*/
|
||||
clutter_config_read ();
|
||||
|
||||
ClutterCntx = ctx = g_new0 (ClutterMainContext, 1);
|
||||
|
||||
ctx->is_initialized = FALSE;
|
||||
@ -616,6 +806,9 @@ clutter_init_real (GError **error)
|
||||
|
||||
clutter_text_direction = clutter_get_text_direction ();
|
||||
|
||||
/* Initiate event collection */
|
||||
_clutter_backend_init_events (ctx->backend);
|
||||
|
||||
clutter_is_initialized = TRUE;
|
||||
ctx->is_initialized = TRUE;
|
||||
|
||||
@ -863,6 +1056,99 @@ clutter_get_option_group_without_init (void)
|
||||
* allow the common case of argc=NULL, argv=NULL to work.
|
||||
*/
|
||||
|
||||
/**
|
||||
* clutter_init_with_args:
|
||||
* @argc: (inout): a pointer to the number of command line arguments
|
||||
* @argv: (array length=argc) (inout) (allow-none): a pointer to the array
|
||||
* of command line arguments
|
||||
* @parameter_string: (allow-none): a string which is displayed in the
|
||||
* first line of <option>--help</option> output, after
|
||||
* <literal><replaceable>programname</replaceable> [OPTION...]</literal>
|
||||
* @entries: (array) (allow-none): a %NULL terminated array of
|
||||
* #GOptionEntry<!-- -->s describing the options of your program
|
||||
* @translation_domain: (allow-none): a translation domain to use for
|
||||
* translating the <option>--help</option> output for the options in
|
||||
* @entries with gettext(), or %NULL
|
||||
* @error: (allow-none): a return location for a #GError
|
||||
*
|
||||
* This function does the same work as clutter_init(). Additionally,
|
||||
* it allows you to add your own command line options, and it
|
||||
* automatically generates nicely formatted <option>--help</option>
|
||||
* output. Note that your program will be terminated after writing
|
||||
* out the help output. Also note that, in case of error, the
|
||||
* error message will be placed inside @error instead of being
|
||||
* printed on the display.
|
||||
*
|
||||
* Just like clutter_init(), if this function returns an error code then
|
||||
* any subsequent call to any other Clutter API will result in undefined
|
||||
* behaviour - including segmentation faults.
|
||||
*
|
||||
* Return value: %CLUTTER_INIT_SUCCESS if Clutter has been successfully
|
||||
* initialised, or other values or #ClutterInitError in case of
|
||||
* error.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
ClutterInitError
|
||||
clutter_init_with_args (int *argc,
|
||||
char ***argv,
|
||||
const char *parameter_string,
|
||||
GOptionEntry *entries,
|
||||
const char *translation_domain,
|
||||
GError **error)
|
||||
{
|
||||
GOptionContext *context;
|
||||
GOptionGroup *group;
|
||||
gboolean res;
|
||||
ClutterMainContext *ctx;
|
||||
|
||||
if (clutter_is_initialized)
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
|
||||
clutter_base_init ();
|
||||
|
||||
ctx = _clutter_context_get_default ();
|
||||
|
||||
if (!ctx->defer_display_setup)
|
||||
{
|
||||
#if 0
|
||||
if (argc && *argc > 0 && *argv)
|
||||
g_set_prgname ((*argv)[0]);
|
||||
#endif
|
||||
|
||||
context = g_option_context_new (parameter_string);
|
||||
|
||||
group = clutter_get_option_group ();
|
||||
g_option_context_add_group (context, group);
|
||||
|
||||
group = cogl_get_option_group ();
|
||||
g_option_context_add_group (context, group);
|
||||
|
||||
if (entries)
|
||||
g_option_context_add_main_entries (context, entries, translation_domain);
|
||||
|
||||
res = g_option_context_parse (context, argc, argv, error);
|
||||
g_option_context_free (context);
|
||||
|
||||
/* if res is FALSE, the error is filled for
|
||||
* us by g_option_context_parse()
|
||||
*/
|
||||
if (!res)
|
||||
{
|
||||
/* if there has been an error in the initialization, the
|
||||
* error id will be preserved inside the GError code
|
||||
*/
|
||||
if (error && *error)
|
||||
return (*error)->code;
|
||||
else
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
return clutter_init_real (error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_parse_args (int *argc,
|
||||
@ -914,7 +1200,9 @@ clutter_parse_args (int *argc,
|
||||
* This function will not abort in case of errors during
|
||||
* initialization; clutter_init() will print out the error message on
|
||||
* stderr, and will return an error code. It is up to the application
|
||||
* code to handle this case.
|
||||
* code to handle this case. If you need to display the error message
|
||||
* yourself, you can use clutter_init_with_args(), which takes a #GError
|
||||
* pointer.
|
||||
*
|
||||
* If this function fails, and returns an error code, any subsequent
|
||||
* Clutter API will have undefined behaviour - including segmentation
|
||||
@ -1033,9 +1321,9 @@ event_click_count_generate (ClutterEvent *event)
|
||||
previous_button_number = device->previous_button_number;
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Restoring previous click count:%d (device:%s, time:%u)",
|
||||
"Restoring previous click count:%d (device:%d, time:%u)",
|
||||
click_count,
|
||||
clutter_input_device_get_device_name (device),
|
||||
clutter_input_device_get_device_id (device),
|
||||
previous_time);
|
||||
}
|
||||
else
|
||||
@ -1089,9 +1377,9 @@ event_click_count_generate (ClutterEvent *event)
|
||||
|
||||
if (event->type == CLUTTER_BUTTON_PRESS && device != NULL)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "Storing click count: %d (device:%s, time:%u)",
|
||||
CLUTTER_NOTE (EVENT, "Storing click count: %d (device:%d, time:%u)",
|
||||
click_count,
|
||||
clutter_input_device_get_device_name (device),
|
||||
clutter_input_device_get_device_id (device),
|
||||
previous_time);
|
||||
|
||||
device->click_count = click_count;
|
||||
@ -1105,13 +1393,26 @@ event_click_count_generate (ClutterEvent *event)
|
||||
static inline void
|
||||
emit_event_chain (ClutterEvent *event)
|
||||
{
|
||||
static gboolean lock = FALSE;
|
||||
|
||||
if (event->any.source == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No source set, discarding event");
|
||||
return;
|
||||
}
|
||||
|
||||
/* reentrancy check */
|
||||
if (lock != FALSE)
|
||||
{
|
||||
g_warning ("Tried emitting event during event delivery, bailing out.");
|
||||
return;
|
||||
}
|
||||
|
||||
lock = TRUE;
|
||||
|
||||
_clutter_actor_handle_event (event->any.source, event);
|
||||
|
||||
lock = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1187,8 +1488,8 @@ emit_touch_event (ClutterEvent *event,
|
||||
}
|
||||
|
||||
static inline void
|
||||
process_key_event (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
emit_keyboard_event (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
if (_clutter_event_process_filters (event))
|
||||
return;
|
||||
@ -1199,6 +1500,21 @@ process_key_event (ClutterEvent *event,
|
||||
emit_event_chain (event);
|
||||
}
|
||||
|
||||
static inline void
|
||||
process_key_event (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (device_class->process_kbd_a11y_event)
|
||||
{
|
||||
device_class->process_kbd_a11y_event (event, device, emit_keyboard_event);
|
||||
return;
|
||||
}
|
||||
|
||||
emit_keyboard_event (event, device);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_off_stage (ClutterActor *stage,
|
||||
gfloat x,
|
||||
@ -1252,168 +1568,6 @@ clutter_do_event (ClutterEvent *event)
|
||||
_clutter_stage_queue_event (event->any.stage, event, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
create_crossing_event (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
ClutterEventType event_type,
|
||||
ClutterActor *source,
|
||||
ClutterActor *related,
|
||||
graphene_point_t coords,
|
||||
uint32_t time)
|
||||
{
|
||||
ClutterEvent *event;
|
||||
|
||||
event = clutter_event_new (event_type);
|
||||
event->crossing.time = time;
|
||||
event->crossing.flags = 0;
|
||||
event->crossing.stage = stage;
|
||||
event->crossing.source = source;
|
||||
event->crossing.x = coords.x;
|
||||
event->crossing.y = coords.y;
|
||||
event->crossing.related = related;
|
||||
event->crossing.sequence = sequence;
|
||||
clutter_event_set_device (event, device);
|
||||
|
||||
/* we need to make sure that this event is processed
|
||||
* before any other event we might have queued up until
|
||||
* now, so we go on, and synthesize the event emission
|
||||
* ourselves
|
||||
*/
|
||||
_clutter_process_event (event);
|
||||
|
||||
clutter_event_free (event);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_update_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t point,
|
||||
uint32_t time,
|
||||
ClutterActor *new_actor,
|
||||
gboolean emit_crossing)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterActor *old_actor;
|
||||
gboolean device_actor_changed;
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
|
||||
g_assert (device_type != CLUTTER_KEYBOARD_DEVICE &&
|
||||
device_type != CLUTTER_PAD_DEVICE);
|
||||
|
||||
old_actor = clutter_stage_get_device_actor (stage, device, sequence);
|
||||
device_actor_changed = new_actor != old_actor;
|
||||
|
||||
clutter_stage_update_device_entry (stage,
|
||||
device, sequence,
|
||||
point,
|
||||
new_actor);
|
||||
|
||||
if (device_actor_changed)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Updating actor under cursor (device %s, at %.2f, %.2f): %s",
|
||||
clutter_input_device_get_device_name (device),
|
||||
point.x,
|
||||
point.y,
|
||||
_clutter_actor_get_debug_name (new_actor));
|
||||
|
||||
if (old_actor && emit_crossing)
|
||||
{
|
||||
create_crossing_event (stage,
|
||||
device, sequence,
|
||||
CLUTTER_LEAVE,
|
||||
old_actor, new_actor,
|
||||
point, time);
|
||||
}
|
||||
|
||||
if (new_actor && emit_crossing)
|
||||
{
|
||||
create_crossing_event (stage,
|
||||
device, sequence,
|
||||
CLUTTER_ENTER,
|
||||
new_actor, old_actor,
|
||||
point, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_repick_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
graphene_point_t point;
|
||||
ClutterActor *new_actor;
|
||||
|
||||
clutter_stage_get_device_coords (stage, device, NULL, &point);
|
||||
new_actor =
|
||||
clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_REACTIVE,
|
||||
point.x, point.y);
|
||||
|
||||
clutter_stage_update_device (stage,
|
||||
device, NULL,
|
||||
point,
|
||||
CLUTTER_CURRENT_TIME,
|
||||
new_actor,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
update_device_for_event (ClutterStage *stage,
|
||||
ClutterEvent *event,
|
||||
gboolean emit_crossing)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
||||
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
||||
ClutterActor *new_actor;
|
||||
graphene_point_t point;
|
||||
uint32_t time;
|
||||
|
||||
clutter_event_get_coords (event, &point.x, &point.y);
|
||||
time = clutter_event_get_time (event);
|
||||
|
||||
new_actor =
|
||||
_clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE);
|
||||
|
||||
/* Picking should never fail, but if it does, we bail out here */
|
||||
g_return_val_if_fail (new_actor != NULL, NULL);
|
||||
|
||||
clutter_stage_update_device (stage,
|
||||
device, sequence,
|
||||
point,
|
||||
time,
|
||||
new_actor,
|
||||
emit_crossing);
|
||||
|
||||
return new_actor;
|
||||
}
|
||||
|
||||
static void
|
||||
remove_device_for_event (ClutterStage *stage,
|
||||
ClutterEvent *event,
|
||||
gboolean emit_crossing)
|
||||
{
|
||||
ClutterInputDevice *device = clutter_event_get_device (event);
|
||||
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
||||
graphene_point_t point;
|
||||
uint32_t time;
|
||||
|
||||
clutter_event_get_coords (event, &point.x, &point.y);
|
||||
time = clutter_event_get_time (event);
|
||||
|
||||
clutter_stage_update_device (stage,
|
||||
device, sequence,
|
||||
point,
|
||||
time,
|
||||
NULL,
|
||||
TRUE);
|
||||
|
||||
clutter_stage_remove_device_entry (stage, device, sequence);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_clutter_process_event_details (ClutterActor *stage,
|
||||
ClutterMainContext *context,
|
||||
@ -1438,9 +1592,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
|
||||
@ -1472,7 +1623,9 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
emit_crossing_event (event, device);
|
||||
|
||||
actor = update_device_for_event (CLUTTER_STAGE (stage), event, FALSE);
|
||||
actor = clutter_input_device_update (device, NULL,
|
||||
CLUTTER_STAGE (stage), FALSE,
|
||||
event);
|
||||
if (actor != stage)
|
||||
{
|
||||
ClutterEvent *crossing;
|
||||
@ -1498,14 +1651,13 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
*/
|
||||
if (event->any.source == stage &&
|
||||
event->crossing.related == NULL &&
|
||||
clutter_stage_get_device_actor (CLUTTER_STAGE (stage), device, NULL) != stage)
|
||||
device->cursor_actor != stage)
|
||||
{
|
||||
ClutterEvent *crossing;
|
||||
|
||||
crossing = clutter_event_copy (event);
|
||||
crossing->crossing.related = stage;
|
||||
crossing->crossing.source =
|
||||
clutter_stage_get_device_actor (CLUTTER_STAGE (stage), device, NULL);
|
||||
crossing->crossing.source = device->cursor_actor;
|
||||
|
||||
emit_crossing_event (crossing, device);
|
||||
clutter_event_free (crossing);
|
||||
@ -1513,6 +1665,16 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
emit_crossing_event (event, device);
|
||||
break;
|
||||
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
event->any.source = stage;
|
||||
|
||||
if (_clutter_event_process_filters (event))
|
||||
break;
|
||||
|
||||
/* the stage did not handle the event, so we just quit */
|
||||
clutter_stage_event (CLUTTER_STAGE (stage), event);
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
if (clutter_backend_is_display_server (backend) &&
|
||||
!(event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC))
|
||||
@ -1568,6 +1730,7 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
case CLUTTER_TOUCHPAD_PINCH:
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
{
|
||||
ClutterActor *actor;
|
||||
gfloat x, y;
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
@ -1611,32 +1774,24 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
}
|
||||
|
||||
/* We need to repick on both motion and button press events, the
|
||||
* latter is only needed for X11 (there the device actor might be
|
||||
* stale because we don't always receive motion events).
|
||||
*/
|
||||
if (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_MOTION)
|
||||
{
|
||||
event->any.source =
|
||||
update_device_for_event (CLUTTER_STAGE (stage), event, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
event->any.source =
|
||||
clutter_stage_get_device_actor (CLUTTER_STAGE (stage),
|
||||
device,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (event->any.source == NULL)
|
||||
actor = clutter_input_device_update (device, NULL,
|
||||
CLUTTER_STAGE (stage),
|
||||
TRUE, event);
|
||||
if (actor == NULL)
|
||||
break;
|
||||
|
||||
event->any.source = actor;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* use the source already set in the synthetic event */
|
||||
actor = event->any.source;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Reactive event received at %.2f, %.2f - actor: %p",
|
||||
x, y,
|
||||
event->any.source);
|
||||
actor);
|
||||
|
||||
/* button presses and releases need a click count */
|
||||
if (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
@ -1690,8 +1845,13 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
case CLUTTER_TOUCH_END:
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterEventSequence *sequence;
|
||||
gfloat x, y;
|
||||
|
||||
sequence =
|
||||
clutter_event_get_event_sequence (event);
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
/* Only do a pick to find the source if source is not already set
|
||||
@ -1716,45 +1876,44 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_END ||
|
||||
event->type == CLUTTER_TOUCH_CANCEL)
|
||||
remove_device_for_event (CLUTTER_STAGE (stage), event, TRUE);
|
||||
_clutter_input_device_remove_event_sequence (device, event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_BEGIN ||
|
||||
event->type == CLUTTER_TOUCH_UPDATE)
|
||||
{
|
||||
event->any.source =
|
||||
update_device_for_event (CLUTTER_STAGE (stage), event, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
event->any.source =
|
||||
clutter_stage_get_device_actor (CLUTTER_STAGE (stage),
|
||||
device,
|
||||
event->touch.sequence);
|
||||
}
|
||||
|
||||
if (event->any.source == NULL)
|
||||
actor = clutter_input_device_update (device, sequence,
|
||||
CLUTTER_STAGE (stage),
|
||||
TRUE, event);
|
||||
if (actor == NULL)
|
||||
break;
|
||||
|
||||
event->any.source = actor;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* use the source already set in the synthetic event */
|
||||
actor = event->any.source;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Reactive event received at %.2f, %.2f - actor: %p",
|
||||
x, y,
|
||||
event->any.source);
|
||||
actor);
|
||||
|
||||
emit_touch_event (event, device);
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_END ||
|
||||
event->type == CLUTTER_TOUCH_CANCEL)
|
||||
remove_device_for_event (CLUTTER_STAGE (stage), event, TRUE);
|
||||
_clutter_input_device_remove_event_sequence (device, event);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
clutter_input_device_update_from_tool (clutter_event_get_source_device (event),
|
||||
clutter_event_get_device_tool (event));
|
||||
|
||||
if (_clutter_event_process_filters (event))
|
||||
break;
|
||||
|
||||
@ -1766,26 +1925,20 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
_clutter_event_process_filters (event);
|
||||
case CLUTTER_STAGE_STATE:
|
||||
/* focus - forward to stage */
|
||||
event->any.source = stage;
|
||||
if (!_clutter_event_process_filters (event))
|
||||
clutter_stage_event (CLUTTER_STAGE (stage), event);
|
||||
break;
|
||||
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
_clutter_event_process_filters (event);
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
if (device_type == CLUTTER_POINTER_DEVICE ||
|
||||
device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE ||
|
||||
device_type == CLUTTER_CURSOR_DEVICE)
|
||||
remove_device_for_event (CLUTTER_STAGE (stage), event, TRUE);
|
||||
|
||||
break;
|
||||
}
|
||||
_clutter_event_process_filters (event);
|
||||
break;
|
||||
|
||||
case CLUTTER_EVENT_LAST:
|
||||
break;
|
||||
@ -1804,10 +1957,8 @@ _clutter_process_event (ClutterEvent *event)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterActor *stage;
|
||||
ClutterSeat *seat;
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
seat = clutter_backend_get_default_seat (context->backend);
|
||||
|
||||
stage = CLUTTER_ACTOR (event->any.stage);
|
||||
if (stage == NULL)
|
||||
@ -1822,7 +1973,6 @@ _clutter_process_event (ClutterEvent *event)
|
||||
*/
|
||||
context->current_event = g_slist_prepend (context->current_event, event);
|
||||
|
||||
clutter_seat_handle_event_post (seat, event);
|
||||
_clutter_process_event_details (stage, context, event);
|
||||
|
||||
context->current_event = g_slist_delete_link (context->current_event, context->current_event);
|
||||
@ -1925,7 +2075,7 @@ clutter_threads_remove_repaint_func (guint handle_id)
|
||||
if (repaint_func->notify)
|
||||
repaint_func->notify (repaint_func->data);
|
||||
|
||||
g_free (repaint_func);
|
||||
g_slice_free (ClutterRepaintFunction, repaint_func);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -2032,7 +2182,7 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
|
||||
repaint_func = g_new0 (ClutterRepaintFunction, 1);
|
||||
repaint_func = g_slice_new (ClutterRepaintFunction);
|
||||
|
||||
repaint_func->id = context->last_repaint_id++;
|
||||
|
||||
@ -2096,7 +2246,7 @@ _clutter_run_repaint_functions (ClutterRepaintFlags flags)
|
||||
if (repaint_func->notify != NULL)
|
||||
repaint_func->notify (repaint_func->data);
|
||||
|
||||
g_free (repaint_func);
|
||||
g_slice_free (ClutterRepaintFunction, repaint_func);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2139,21 +2289,23 @@ _clutter_clear_events_queue (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterEvent *event;
|
||||
GAsyncQueue *events_queue;
|
||||
|
||||
if (!context->events_queue)
|
||||
return;
|
||||
|
||||
/* Lock the queue for as long as it lives */
|
||||
g_async_queue_lock (context->events_queue);
|
||||
|
||||
while ((event = g_async_queue_try_pop_unlocked (context->events_queue)))
|
||||
clutter_event_free (event);
|
||||
|
||||
events_queue = context->events_queue;
|
||||
g_async_queue_unref (context->events_queue);
|
||||
context->events_queue = NULL;
|
||||
}
|
||||
|
||||
g_async_queue_unlock (events_queue);
|
||||
g_async_queue_unref (events_queue);
|
||||
ClutterPickMode
|
||||
_clutter_context_get_pick_mode (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
|
||||
return context->pick_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2186,25 +2338,6 @@ clutter_remove_debug_flags (ClutterDebugFlag debug_flags,
|
||||
clutter_pick_debug_flags &= ~pick_flags;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_debug_set_max_render_time_constant (int max_render_time_constant_us)
|
||||
{
|
||||
clutter_max_render_time_constant_us = max_render_time_constant_us;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_get_debug_flags (ClutterDebugFlag *debug_flags,
|
||||
ClutterDrawDebugFlag *draw_flags,
|
||||
ClutterPickDebugFlag *pick_flags)
|
||||
{
|
||||
if (debug_flags)
|
||||
*debug_flags = clutter_debug_flags;
|
||||
if (draw_flags)
|
||||
*draw_flags = clutter_paint_debug_flags;
|
||||
if (pick_flags)
|
||||
*pick_flags = clutter_pick_debug_flags;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_set_sync_to_vblank (gboolean sync_to_vblank)
|
||||
{
|
||||
|
@ -53,8 +53,6 @@ typedef enum
|
||||
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
|
||||
CLUTTER_DEBUG_CLIPPING = 1 << 15,
|
||||
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16,
|
||||
CLUTTER_DEBUG_FRAME_TIMINGS = 1 << 17,
|
||||
CLUTTER_DEBUG_DETAILED_TRACE = 1 << 18,
|
||||
} ClutterDebugFlag;
|
||||
|
||||
typedef enum
|
||||
@ -64,17 +62,15 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
|
||||
CLUTTER_DEBUG_REDRAWS = 1 << 2,
|
||||
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
|
||||
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
|
||||
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
|
||||
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
|
||||
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
|
||||
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
|
||||
CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME = 1 << 9,
|
||||
CLUTTER_DEBUG_PAINT_MAX_RENDER_TIME = 1 << 10,
|
||||
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
|
||||
CLUTTER_DEBUG_REDRAWS = 1 << 2,
|
||||
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
|
||||
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
|
||||
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
|
||||
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
|
||||
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
|
||||
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
|
||||
} ClutterDrawDebugFlag;
|
||||
|
||||
/**
|
||||
@ -92,7 +88,7 @@ typedef enum
|
||||
* @CLUTTER_INIT_ERROR_BACKEND: Backend initialisation failed
|
||||
* @CLUTTER_INIT_ERROR_INTERNAL: Internal error
|
||||
*
|
||||
* Error conditions returned by clutter_init().
|
||||
* Error conditions returned by clutter_init() and clutter_init_with_args().
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
@ -127,6 +123,13 @@ void clutter_base_init (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInitError clutter_init (int *argc,
|
||||
char ***argv) G_GNUC_WARN_UNUSED_RESULT;
|
||||
CLUTTER_EXPORT
|
||||
ClutterInitError clutter_init_with_args (int *argc,
|
||||
char ***argv,
|
||||
const char *parameter_string,
|
||||
GOptionEntry *entries,
|
||||
const char *translation_domain,
|
||||
GError **error) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GOptionGroup * clutter_get_option_group (void);
|
||||
@ -193,9 +196,6 @@ void clutter_remove_debug_flags (ClutterDebugFla
|
||||
ClutterDrawDebugFlag draw_flags,
|
||||
ClutterPickDebugFlag pick_flags);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_debug_set_max_render_time_constant (int max_render_time_constant_us);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _CLUTTER_MAIN_H__ */
|
||||
|
@ -26,8 +26,6 @@
|
||||
#define __CLUTTER_H_INSIDE__
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-damage-history.h"
|
||||
#include "clutter-event-private.h"
|
||||
#include "clutter-input-device-private.h"
|
||||
#include "clutter-input-pointer-a11y-private.h"
|
||||
@ -35,8 +33,8 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-stage-view.h"
|
||||
#include "clutter-stage-view-private.h"
|
||||
#include "clutter.h"
|
||||
#include "cogl/clutter-stage-cogl.h"
|
||||
#include "clutter/x11/clutter-backend-x11.h"
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_stage_peek_stage_views (ClutterStage *stage);
|
||||
@ -52,11 +50,10 @@ CLUTTER_EXPORT
|
||||
int64_t clutter_stage_get_frame_counter (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_capture_view_into (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
cairo_rectangle_int_t *rect,
|
||||
uint8_t *data,
|
||||
int stride);
|
||||
void clutter_stage_capture_into (ClutterStage *stage,
|
||||
gboolean paint,
|
||||
cairo_rectangle_int_t *rect,
|
||||
uint8_t *data);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_clear_stage_views (ClutterStage *stage);
|
||||
@ -78,29 +75,6 @@ CLUTTER_EXPORT
|
||||
gboolean clutter_seat_handle_event_post (ClutterSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_update_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t point,
|
||||
uint32_t time,
|
||||
ClutterActor *new_actor,
|
||||
gboolean emit_crossing);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_get_device_coords (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_repick_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_get_debug_flags (ClutterDebugFlag *debug_flags,
|
||||
ClutterDrawDebugFlag *draw_flags,
|
||||
ClutterPickDebugFlag *pick_flags);
|
||||
|
||||
#undef __CLUTTER_H_INSIDE__
|
||||
|
||||
#endif /* __CLUTTER_MUTTER_H__ */
|
||||
|
@ -60,30 +60,6 @@
|
||||
* #ClutterOffscreenEffectClass.create_texture() virtual function; no chain up
|
||||
* to the #ClutterOffscreenEffect implementation is required in this
|
||||
* case.
|
||||
*
|
||||
* ## Paint nodes
|
||||
*
|
||||
* #ClutterOffscreenEffect generates the following paint node tree:
|
||||
*
|
||||
* |[<!-- language="plain" -->
|
||||
* Effect
|
||||
* ├─────────┐
|
||||
* Layer Pipeline
|
||||
* │
|
||||
* Actor
|
||||
* ]|
|
||||
*
|
||||
* When the actor contents are cached, the generated paint node tree
|
||||
* looks like this:
|
||||
*
|
||||
* |[<!-- language="plain" -->
|
||||
* Effect
|
||||
* │
|
||||
* Pipeline
|
||||
* ]|
|
||||
*
|
||||
* In both cases, the "Pipeline" node is created with the return value
|
||||
* of #ClutterOffscreenEffectClass.create_pipeline().
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
@ -99,20 +75,20 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-paint-context-private.h"
|
||||
#include "clutter-paint-node-private.h"
|
||||
#include "clutter-paint-nodes.h"
|
||||
#include "clutter-paint-volume-private.h"
|
||||
#include "clutter-actor-box-private.h"
|
||||
|
||||
struct _ClutterOffscreenEffectPrivate
|
||||
{
|
||||
CoglOffscreen *offscreen;
|
||||
CoglHandle offscreen;
|
||||
CoglPipeline *pipeline;
|
||||
CoglHandle texture;
|
||||
|
||||
ClutterActor *actor;
|
||||
ClutterActor *stage;
|
||||
|
||||
graphene_point3d_t position;
|
||||
|
||||
int fbo_offset_x;
|
||||
int fbo_offset_y;
|
||||
|
||||
@ -123,6 +99,8 @@ struct _ClutterOffscreenEffectPrivate
|
||||
int target_width;
|
||||
int target_height;
|
||||
|
||||
gint old_opacity_override;
|
||||
|
||||
gulong purge_handler_id;
|
||||
};
|
||||
|
||||
@ -142,7 +120,7 @@ clutter_offscreen_effect_set_actor (ClutterActorMeta *meta,
|
||||
meta_class->set_actor (meta, actor);
|
||||
|
||||
/* clear out the previous state */
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
/* we keep a back pointer here, to avoid going through the ActorMeta */
|
||||
priv->actor = clutter_actor_meta_get_actor (meta);
|
||||
@ -182,29 +160,10 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self,
|
||||
filter, filter);
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_offscreen_effect_real_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglPipeline *pipeline;
|
||||
float resource_scale;
|
||||
|
||||
resource_scale = clutter_actor_get_real_resource_scale (priv->actor);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
ensure_pipeline_filter_for_scale (effect, resource_scale);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, texture);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
video_memory_purged (ClutterOffscreenEffect *self)
|
||||
{
|
||||
g_clear_object (&self->priv->offscreen);
|
||||
g_clear_pointer (&self->priv->offscreen, cogl_object_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -214,12 +173,8 @@ update_fbo (ClutterEffect *effect,
|
||||
float resource_scale)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectClass *offscreen_class =
|
||||
CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (self);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
ClutterActor *stage_actor;
|
||||
CoglOffscreen *offscreen;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
stage_actor = clutter_actor_get_stage (priv->actor);
|
||||
if (stage_actor != priv->stage)
|
||||
@ -256,25 +211,35 @@ update_fbo (ClutterEffect *effect,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (priv->pipeline == NULL)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
priv->pipeline = cogl_pipeline_new (ctx);
|
||||
ensure_pipeline_filter_for_scale (self, resource_scale);
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
priv->texture =
|
||||
clutter_offscreen_effect_create_texture (self, target_width, target_height);
|
||||
if (priv->texture == NULL)
|
||||
return FALSE;
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->texture);
|
||||
|
||||
priv->target_width = target_width;
|
||||
priv->target_height = target_height;
|
||||
|
||||
offscreen = cogl_offscreen_new_with_texture (priv->texture);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
|
||||
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
|
||||
if (priv->offscreen == NULL)
|
||||
{
|
||||
g_warning ("Failed to create offscreen effect framebuffer: %s",
|
||||
error->message);
|
||||
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
||||
|
||||
g_object_unref (offscreen);
|
||||
cogl_clear_object (&priv->pipeline);
|
||||
cogl_object_unref (priv->pipeline);
|
||||
priv->pipeline = NULL;
|
||||
|
||||
priv->target_width = 0;
|
||||
priv->target_height = 0;
|
||||
@ -282,36 +247,35 @@ update_fbo (ClutterEffect *effect,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->offscreen = offscreen;
|
||||
|
||||
cogl_clear_object (&priv->pipeline);
|
||||
priv->pipeline = offscreen_class->create_pipeline (self, priv->texture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
CoglFramebuffer *offscreen;
|
||||
ClutterActorBox raw_box, box;
|
||||
ClutterActor *stage;
|
||||
graphene_matrix_t projection, modelview, transform;
|
||||
CoglMatrix projection, old_modelview, modelview;
|
||||
const ClutterPaintVolume *volume;
|
||||
CoglColor transparent;
|
||||
gfloat stage_width, stage_height;
|
||||
gfloat target_width = -1, target_height = -1;
|
||||
CoglFramebuffer *framebuffer;
|
||||
float resource_scale;
|
||||
float ceiled_resource_scale;
|
||||
graphene_point3d_t local_offset;
|
||||
gfloat old_viewport[4];
|
||||
|
||||
local_offset = GRAPHENE_POINT3D_INIT (0.0f, 0.0f, 0.0f);
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
goto disable_effect;
|
||||
return FALSE;
|
||||
|
||||
if (priv->actor == NULL)
|
||||
goto disable_effect;
|
||||
return FALSE;
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (priv->actor);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
@ -336,24 +300,18 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
_clutter_paint_volume_copy_static (volume, &mutable_volume);
|
||||
_clutter_paint_volume_get_bounding_box (&mutable_volume, &raw_box);
|
||||
clutter_paint_volume_free (&mutable_volume);
|
||||
|
||||
box = raw_box;
|
||||
_clutter_actor_box_enlarge_for_effects (&box);
|
||||
|
||||
priv->fbo_offset_x = box.x1;
|
||||
priv->fbo_offset_y = box.y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_get_allocation_box (priv->actor, &raw_box);
|
||||
|
||||
box = raw_box;
|
||||
_clutter_actor_box_enlarge_for_effects (&box);
|
||||
|
||||
priv->fbo_offset_x = box.x1 - raw_box.x1;
|
||||
priv->fbo_offset_y = box.y1 - raw_box.y1;
|
||||
}
|
||||
|
||||
box = raw_box;
|
||||
_clutter_actor_box_enlarge_for_effects (&box);
|
||||
|
||||
priv->fbo_offset_x = box.x1 - raw_box.x1;
|
||||
priv->fbo_offset_y = box.y1 - raw_box.y1;
|
||||
|
||||
clutter_actor_box_scale (&box, ceiled_resource_scale);
|
||||
clutter_actor_box_get_size (&box, &target_width, &target_height);
|
||||
|
||||
@ -362,9 +320,12 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
|
||||
/* First assert that the framebuffer is the right size... */
|
||||
if (!update_fbo (effect, target_width, target_height, resource_scale))
|
||||
goto disable_effect;
|
||||
return FALSE;
|
||||
|
||||
offscreen = COGL_FRAMEBUFFER (priv->offscreen);
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &old_modelview);
|
||||
|
||||
clutter_paint_context_push_framebuffer (paint_context, priv->offscreen);
|
||||
|
||||
/* We don't want the FBO contents to be transformed. That could waste memory
|
||||
* (e.g. during zoom), or result in something that's not rectangular (clipped
|
||||
@ -374,46 +335,67 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
* contents on screen...
|
||||
*/
|
||||
clutter_actor_get_transform (priv->stage, &modelview);
|
||||
graphene_matrix_init_translate (&transform,
|
||||
&GRAPHENE_POINT3D_INIT (-priv->fbo_offset_x,
|
||||
-priv->fbo_offset_y,
|
||||
0.0));
|
||||
graphene_matrix_scale (&transform,
|
||||
stage_width / target_width,
|
||||
stage_height / target_height,
|
||||
1.0);
|
||||
graphene_matrix_multiply (&transform, &modelview, &modelview);
|
||||
cogl_framebuffer_set_modelview_matrix (offscreen, &modelview);
|
||||
cogl_framebuffer_set_modelview_matrix (priv->offscreen, &modelview);
|
||||
|
||||
/* Set up the viewport so that it has the minimal size required to render any
|
||||
* pixel in the FBO without clipping.
|
||||
/* Save the original viewport for calculating priv->position */
|
||||
_clutter_stage_get_viewport (CLUTTER_STAGE (priv->stage),
|
||||
&old_viewport[0],
|
||||
&old_viewport[1],
|
||||
&old_viewport[2],
|
||||
&old_viewport[3]);
|
||||
|
||||
/* Set up the viewport so that it has the same size as the stage (avoid
|
||||
* distortion), but translated to account for the FBO offset...
|
||||
*/
|
||||
cogl_framebuffer_set_viewport (offscreen,
|
||||
0,
|
||||
0,
|
||||
target_width,
|
||||
target_height);
|
||||
cogl_framebuffer_set_viewport (priv->offscreen,
|
||||
-priv->fbo_offset_x,
|
||||
-priv->fbo_offset_y,
|
||||
stage_width,
|
||||
stage_height);
|
||||
|
||||
/* Copy the stage's projection matrix across to the offscreen */
|
||||
/* Copy the stage's projection matrix across to the framebuffer */
|
||||
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage),
|
||||
&projection);
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (offscreen, &projection);
|
||||
/* Now save the global position of the effect (not just of the actor).
|
||||
* It doesn't appear anyone actually uses this yet, but get_target_rect is
|
||||
* documented as returning it. So we should...
|
||||
*/
|
||||
_clutter_util_fully_transform_vertices (&old_modelview,
|
||||
&projection,
|
||||
old_viewport,
|
||||
&local_offset,
|
||||
&priv->position,
|
||||
1);
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (priv->offscreen, &projection);
|
||||
|
||||
cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
|
||||
cogl_framebuffer_clear (priv->offscreen,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
COGL_BUFFER_BIT_DEPTH,
|
||||
&transparent);
|
||||
|
||||
cogl_framebuffer_push_matrix (priv->offscreen);
|
||||
|
||||
/* Override the actor's opacity to fully opaque - we paint the offscreen
|
||||
* texture with the actor's paint opacity, so we need to do this to avoid
|
||||
* multiplying the opacity twice.
|
||||
*/
|
||||
priv->old_opacity_override =
|
||||
clutter_actor_get_opacity_override (priv->actor);
|
||||
clutter_actor_set_opacity_override (priv->actor, 0xff);
|
||||
|
||||
return TRUE;
|
||||
|
||||
disable_effect:
|
||||
g_clear_object (&priv->offscreen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
ClutterPaintNode *pipeline_node;
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
guint8 paint_opacity;
|
||||
|
||||
paint_opacity = clutter_actor_get_paint_opacity (priv->actor);
|
||||
@ -424,125 +406,97 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
|
||||
paint_opacity,
|
||||
paint_opacity);
|
||||
|
||||
pipeline_node = clutter_pipeline_node_new (priv->pipeline);
|
||||
clutter_paint_node_set_static_name (pipeline_node,
|
||||
"ClutterOffscreenEffect (pipeline)");
|
||||
clutter_paint_node_add_child (node, pipeline_node);
|
||||
|
||||
/* At this point we are in stage coordinates translated so if
|
||||
* we draw our texture using a textured quad the size of the paint
|
||||
* box then we will overlay where the actor would have drawn if it
|
||||
* hadn't been redirected offscreen.
|
||||
*/
|
||||
clutter_paint_node_add_rectangle (pipeline_node,
|
||||
&(ClutterActorBox) {
|
||||
0.f, 0.f,
|
||||
cogl_texture_get_width (priv->texture),
|
||||
cogl_texture_get_height (priv->texture),
|
||||
});
|
||||
|
||||
clutter_paint_node_unref (pipeline_node);
|
||||
cogl_framebuffer_draw_textured_rectangle (framebuffer,
|
||||
priv->pipeline,
|
||||
0, 0,
|
||||
cogl_texture_get_width (priv->texture),
|
||||
cogl_texture_get_height (priv->texture),
|
||||
0.0, 0.0,
|
||||
1.0, 1.0);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
graphene_matrix_t transform;
|
||||
float unscale;
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
CoglMatrix modelview;
|
||||
float resource_scale;
|
||||
|
||||
unscale = 1.0 / clutter_actor_get_resource_scale (priv->actor);
|
||||
graphene_matrix_init_scale (&transform, unscale, unscale, 1.0);
|
||||
graphene_matrix_translate (&transform,
|
||||
&GRAPHENE_POINT3D_INIT (priv->fbo_offset_x,
|
||||
priv->fbo_offset_y,
|
||||
0.0));
|
||||
cogl_framebuffer_push_matrix (framebuffer);
|
||||
|
||||
if (!graphene_matrix_is_identity (&transform))
|
||||
/* The current modelview matrix is *almost* perfect already. It's only
|
||||
* missing a correction for the expanded FBO and offset rendering within...
|
||||
*/
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
|
||||
|
||||
resource_scale = clutter_actor_get_resource_scale (priv->actor);
|
||||
|
||||
if (resource_scale != 1.0f)
|
||||
{
|
||||
ClutterPaintNode *transform_node;
|
||||
|
||||
transform_node = clutter_transform_node_new (&transform);
|
||||
clutter_paint_node_set_static_name (transform_node,
|
||||
"ClutterOffscreenEffect (transform)");
|
||||
clutter_paint_node_add_child (node, transform_node);
|
||||
clutter_paint_node_unref (transform_node);
|
||||
|
||||
node = transform_node;
|
||||
float paint_scale = 1.0f / resource_scale;
|
||||
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
|
||||
}
|
||||
|
||||
cogl_matrix_translate (&modelview,
|
||||
priv->fbo_offset_x,
|
||||
priv->fbo_offset_y,
|
||||
0.0f);
|
||||
cogl_framebuffer_set_modelview_matrix (framebuffer, &modelview);
|
||||
|
||||
/* paint the target material; this is virtualized for
|
||||
* sub-classes that require special hand-holding
|
||||
*/
|
||||
clutter_offscreen_effect_paint_target (effect, node, paint_context);
|
||||
clutter_offscreen_effect_paint_target (effect, paint_context);
|
||||
|
||||
cogl_framebuffer_pop_matrix (framebuffer);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
CoglFramebuffer *framebuffer;
|
||||
|
||||
g_warn_if_fail (priv->offscreen);
|
||||
g_warn_if_fail (priv->pipeline);
|
||||
g_warn_if_fail (priv->actor);
|
||||
|
||||
clutter_offscreen_effect_paint_texture (self, node, paint_context);
|
||||
}
|
||||
/* Restore the previous opacity override */
|
||||
if (priv->actor)
|
||||
{
|
||||
clutter_actor_set_opacity_override (priv->actor,
|
||||
priv->old_opacity_override);
|
||||
}
|
||||
|
||||
static void
|
||||
add_actor_node (ClutterOffscreenEffect *offscreen_effect,
|
||||
ClutterPaintNode *node,
|
||||
int paint_opacity)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
ClutterPaintNode *actor_node;
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_pop_matrix (framebuffer);
|
||||
clutter_paint_context_pop_framebuffer (paint_context);
|
||||
|
||||
actor_node = clutter_actor_node_new (priv->actor, paint_opacity);
|
||||
clutter_paint_node_add_child (node, actor_node);
|
||||
clutter_paint_node_unref (actor_node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_paint_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
ClutterPaintNode *layer_node;
|
||||
CoglFramebuffer *fb;
|
||||
|
||||
fb = COGL_FRAMEBUFFER (priv->offscreen);
|
||||
layer_node = clutter_layer_node_new_to_framebuffer (fb, priv->pipeline);
|
||||
clutter_paint_node_set_static_name (layer_node,
|
||||
"ClutterOffscreenEffect (actor offscreen)");
|
||||
clutter_paint_node_add_child (node, layer_node);
|
||||
clutter_paint_node_unref (layer_node);
|
||||
|
||||
add_actor_node (offscreen_effect, layer_node, 255);
|
||||
clutter_offscreen_effect_paint_texture (self, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
ClutterEffectClass *parent_class =
|
||||
CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class);
|
||||
|
||||
if (flags & CLUTTER_EFFECT_PAINT_BYPASS_EFFECT)
|
||||
{
|
||||
add_actor_node (self, node, -1);
|
||||
g_clear_object (&priv->offscreen);
|
||||
clutter_actor_continue_paint (priv->actor, paint_context);
|
||||
cogl_clear_object (&priv->offscreen);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -550,9 +504,21 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
* then we can just use the cached image in the FBO.
|
||||
*/
|
||||
if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY))
|
||||
parent_class->paint (effect, node, paint_context, flags);
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
||||
gboolean pre_paint_succeeded;
|
||||
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect, paint_context);
|
||||
|
||||
clutter_actor_continue_paint (priv->actor, paint_context);
|
||||
|
||||
if (pre_paint_succeeded)
|
||||
effect_class->post_paint (effect, paint_context);
|
||||
else
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
}
|
||||
else
|
||||
clutter_offscreen_effect_paint_texture (self, node, paint_context);
|
||||
clutter_offscreen_effect_paint_texture (self, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -564,7 +530,7 @@ clutter_offscreen_effect_set_enabled (ClutterActorMeta *meta,
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (meta);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
parent_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
@ -575,7 +541,7 @@ clutter_offscreen_effect_finalize (GObject *gobject)
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (gobject);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
|
||||
@ -590,7 +556,6 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->create_texture = clutter_offscreen_effect_real_create_texture;
|
||||
klass->create_pipeline = clutter_offscreen_effect_real_create_pipeline;
|
||||
klass->paint_target = clutter_offscreen_effect_real_paint_target;
|
||||
|
||||
meta_class->set_actor = clutter_offscreen_effect_set_actor;
|
||||
@ -599,7 +564,6 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
|
||||
effect_class->pre_paint = clutter_offscreen_effect_pre_paint;
|
||||
effect_class->post_paint = clutter_offscreen_effect_post_paint;
|
||||
effect_class->paint = clutter_offscreen_effect_paint;
|
||||
effect_class->paint_node = clutter_offscreen_effect_paint_node;
|
||||
|
||||
gobject_class->finalize = clutter_offscreen_effect_finalize;
|
||||
}
|
||||
@ -640,34 +604,33 @@ clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_offscreen_effect_get_pipeline:
|
||||
* clutter_offscreen_effect_get_target: (skip)
|
||||
* @effect: a #ClutterOffscreenEffect
|
||||
*
|
||||
* Retrieves the pipeline used as a render target for the offscreen
|
||||
* Retrieves the material used as a render target for the offscreen
|
||||
* buffer created by @effect
|
||||
*
|
||||
* You should only use the returned #CoglPipeline when painting. The
|
||||
* returned pipeline might change between different frames.
|
||||
* You should only use the returned #CoglMaterial when painting. The
|
||||
* returned material might change between different frames.
|
||||
*
|
||||
* Return value: (transfer none)(nullable): a #CoglPipeline. The
|
||||
* pipeline is owned by Clutter and it should not be modified
|
||||
* or freed
|
||||
* Return value: (transfer none): a #CoglMaterial or %NULL. The
|
||||
* returned material is owned by Clutter and it should not be
|
||||
* modified or freed
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
CoglPipeline *
|
||||
clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect)
|
||||
CoglMaterial *
|
||||
clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect),
|
||||
NULL);
|
||||
|
||||
return effect->priv->pipeline;
|
||||
return (CoglMaterial *)effect->priv->pipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_offscreen_effect_paint_target:
|
||||
* @effect: a #ClutterOffscreenEffect
|
||||
* @node: a #ClutterPaintNode
|
||||
* @paint_context: a #ClutterPaintContext
|
||||
*
|
||||
* Calls the paint_target() virtual function of the @effect
|
||||
@ -676,13 +639,11 @@ clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect)
|
||||
*/
|
||||
void
|
||||
clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect));
|
||||
|
||||
CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect)->paint_target (effect,
|
||||
node,
|
||||
paint_context);
|
||||
}
|
||||
|
||||
@ -730,6 +691,8 @@ clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,
|
||||
* and %FALSE otherwise
|
||||
*
|
||||
* Since: 1.8
|
||||
*
|
||||
* Deprecated: 1.14: Use clutter_offscreen_effect_get_target_rect() instead
|
||||
*/
|
||||
gboolean
|
||||
clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
||||
@ -753,3 +716,43 @@ clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_offscreen_effect_get_target_rect:
|
||||
* @effect: a #ClutterOffscreenEffect
|
||||
* @rect: (out caller-allocates): return location for the target area
|
||||
*
|
||||
* Retrieves the origin and size of the offscreen buffer used by @effect to
|
||||
* paint the actor to which it has been applied.
|
||||
*
|
||||
* This function should only be called by #ClutterOffscreenEffect
|
||||
* implementations, from within the #ClutterOffscreenEffectClass.paint_target()
|
||||
* virtual function.
|
||||
*
|
||||
* Return value: %TRUE if the offscreen buffer has a valid rectangle,
|
||||
* and %FALSE otherwise
|
||||
*
|
||||
* Since: 1.14
|
||||
*/
|
||||
gboolean
|
||||
clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
|
||||
graphene_rect_t *rect)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), FALSE);
|
||||
g_return_val_if_fail (rect != NULL, FALSE);
|
||||
|
||||
priv = effect->priv;
|
||||
|
||||
if (priv->texture == NULL)
|
||||
return FALSE;
|
||||
|
||||
graphene_rect_init (rect,
|
||||
priv->position.x,
|
||||
priv->position.y,
|
||||
cogl_texture_get_width (priv->texture),
|
||||
cogl_texture_get_height (priv->texture));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -79,10 +79,7 @@ struct _ClutterOffscreenEffectClass
|
||||
CoglHandle (* create_texture) (ClutterOffscreenEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
CoglPipeline* (* create_pipeline) (ClutterOffscreenEffect *effect,
|
||||
CoglTexture *texture);
|
||||
void (* paint_target) (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
/*< private >*/
|
||||
@ -99,25 +96,28 @@ CLUTTER_EXPORT
|
||||
GType clutter_offscreen_effect_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
CoglPipeline * clutter_offscreen_effect_get_pipeline (ClutterOffscreenEffect *effect);
|
||||
CoglMaterial * clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
CoglHandle clutter_offscreen_effect_get_texture (ClutterOffscreenEffect *effect);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_offscreen_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
CLUTTER_EXPORT
|
||||
CoglHandle clutter_offscreen_effect_create_texture (ClutterOffscreenEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
CLUTTER_DEPRECATED_FOR (clutter_offscreen_effect_get_target_rect)
|
||||
gboolean clutter_offscreen_effect_get_target_size (ClutterOffscreenEffect *effect,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
|
||||
graphene_rect_t *rect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_OFFSCREEN_EFFECT_H__ */
|
||||
|
@ -20,17 +20,12 @@
|
||||
|
||||
#include "clutter-paint-context.h"
|
||||
|
||||
ClutterPaintContext *
|
||||
clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip,
|
||||
GArray *clip_frusta,
|
||||
ClutterPaintFlag paint_flags);
|
||||
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip,
|
||||
ClutterPaintFlag paint_flags);
|
||||
|
||||
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);
|
||||
|
||||
CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context);
|
||||
|
||||
const GArray *
|
||||
clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context);
|
||||
|
||||
#endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */
|
||||
|
@ -30,7 +30,6 @@ struct _ClutterPaintContext
|
||||
ClutterStageView *view;
|
||||
|
||||
cairo_region_t *redraw_clip;
|
||||
GArray *clip_frusta;
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
|
||||
@ -40,7 +39,6 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
|
||||
ClutterPaintContext *
|
||||
clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip,
|
||||
GArray *clip_frusta,
|
||||
ClutterPaintFlag paint_flags)
|
||||
{
|
||||
ClutterPaintContext *paint_context;
|
||||
@ -50,7 +48,6 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
g_ref_count_init (&paint_context->ref_count);
|
||||
paint_context->view = view;
|
||||
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
|
||||
paint_context->clip_frusta = g_array_ref (clip_frusta);
|
||||
paint_context->paint_flags = paint_flags;
|
||||
|
||||
framebuffer = clutter_stage_view_get_framebuffer (view);
|
||||
@ -89,10 +86,10 @@ clutter_paint_context_ref (ClutterPaintContext *paint_context)
|
||||
static void
|
||||
clutter_paint_context_dispose (ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_list_free_full (paint_context->framebuffers, g_object_unref);
|
||||
g_list_free_full (paint_context->framebuffers,
|
||||
cogl_object_unref);
|
||||
paint_context->framebuffers = NULL;
|
||||
g_clear_pointer (&paint_context->redraw_clip, cairo_region_destroy);
|
||||
g_clear_pointer (&paint_context->clip_frusta, g_array_unref);
|
||||
}
|
||||
|
||||
void
|
||||
@ -117,7 +114,7 @@ clutter_paint_context_push_framebuffer (ClutterPaintContext *paint_context,
|
||||
CoglFramebuffer *framebuffer)
|
||||
{
|
||||
paint_context->framebuffers = g_list_prepend (paint_context->framebuffers,
|
||||
g_object_ref (framebuffer));
|
||||
cogl_object_ref (framebuffer));
|
||||
}
|
||||
|
||||
void
|
||||
@ -125,7 +122,7 @@ clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_if_fail (paint_context->framebuffers);
|
||||
|
||||
g_object_unref (paint_context->framebuffers->data);
|
||||
cogl_object_unref (paint_context->framebuffers->data);
|
||||
paint_context->framebuffers =
|
||||
g_list_delete_link (paint_context->framebuffers,
|
||||
paint_context->framebuffers);
|
||||
@ -137,12 +134,6 @@ clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context)
|
||||
return paint_context->redraw_clip;
|
||||
}
|
||||
|
||||
const GArray *
|
||||
clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context)
|
||||
{
|
||||
return paint_context->clip_frusta;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_context_get_framebuffer:
|
||||
* @paint_context: The #ClutterPaintContext
|
||||
|
@ -34,7 +34,6 @@ typedef enum _ClutterPaintFlag
|
||||
CLUTTER_PAINT_FLAG_NONE = 0,
|
||||
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
|
||||
CLUTTER_PAINT_FLAG_FORCE_CURSORS = 1 << 1,
|
||||
CLUTTER_PAINT_FLAG_CLEAR = 1 << 2,
|
||||
} ClutterPaintFlag;
|
||||
|
||||
#define CLUTTER_TYPE_PAINT_CONTEXT (clutter_paint_context_get_type ())
|
||||
|
@ -82,7 +82,6 @@ typedef enum
|
||||
{
|
||||
PAINT_OP_INVALID = 0,
|
||||
PAINT_OP_TEX_RECT,
|
||||
PAINT_OP_TEX_RECTS,
|
||||
PAINT_OP_MULTITEX_RECT,
|
||||
PAINT_OP_PRIMITIVE
|
||||
} PaintOpCode;
|
||||
@ -91,7 +90,7 @@ struct _ClutterPaintOperation
|
||||
{
|
||||
PaintOpCode opcode;
|
||||
|
||||
GArray *coords;
|
||||
GArray *multitex_coords;
|
||||
|
||||
union {
|
||||
float texrect[8];
|
||||
@ -112,7 +111,7 @@ void _clutter_paint_operation_paint_primitive (const C
|
||||
void _clutter_paint_node_init_types (void);
|
||||
gpointer _clutter_paint_node_create (GType gtype);
|
||||
|
||||
ClutterPaintNode * _clutter_transform_node_new (const graphene_matrix_t *matrix);
|
||||
ClutterPaintNode * _clutter_transform_node_new (const CoglMatrix *matrix);
|
||||
ClutterPaintNode * _clutter_dummy_node_new (ClutterActor *actor,
|
||||
CoglFramebuffer *framebuffer);
|
||||
|
||||
@ -142,26 +141,6 @@ ClutterPaintNode * clutter_paint_node_get_last_child (Clutter
|
||||
G_GNUC_INTERNAL
|
||||
ClutterPaintNode * clutter_paint_node_get_parent (ClutterPaintNode *node);
|
||||
|
||||
|
||||
#define CLUTTER_TYPE_EFFECT_NODE (clutter_effect_node_get_type ())
|
||||
#define CLUTTER_EFFECT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_EFFECT_NODE, ClutterEffectNode))
|
||||
#define CLUTTER_IS_EFFECT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_EFFECT_NODE))
|
||||
|
||||
/**
|
||||
* ClutterEffectNode:
|
||||
*
|
||||
* The #ClutterEffectNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*/
|
||||
typedef struct _ClutterEffectNode ClutterEffectNode;
|
||||
typedef struct _ClutterEffectNode ClutterEffectNodeClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_effect_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_effect_node_new (ClutterEffect *effect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PAINT_NODE_PRIVATE_H__ */
|
||||
|
@ -60,6 +60,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
@ -234,9 +236,9 @@ clutter_paint_node_init (ClutterPaintNode *self)
|
||||
GType
|
||||
clutter_paint_node_get_type (void)
|
||||
{
|
||||
static size_t paint_node_type_id = 0;
|
||||
static volatile gsize paint_node_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&paint_node_type_id))
|
||||
if (g_once_init_enter (&paint_node_type_id__volatile))
|
||||
{
|
||||
static const GTypeFundamentalInfo finfo = {
|
||||
(G_TYPE_FLAG_CLASSED |
|
||||
@ -272,16 +274,16 @@ clutter_paint_node_get_type (void)
|
||||
&value_table,
|
||||
};
|
||||
|
||||
GType id =
|
||||
GType paint_node_type_id =
|
||||
g_type_register_fundamental (g_type_fundamental_next (),
|
||||
I_("ClutterPaintNode"),
|
||||
&node_info, &finfo,
|
||||
G_TYPE_FLAG_ABSTRACT);
|
||||
|
||||
g_once_init_leave (&paint_node_type_id, id);
|
||||
g_once_init_leave (&paint_node_type_id__volatile, paint_node_type_id);
|
||||
}
|
||||
|
||||
return paint_node_type_id;
|
||||
return paint_node_type_id__volatile;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -775,9 +777,9 @@ clutter_paint_operation_clear (ClutterPaintOperation *op)
|
||||
case PAINT_OP_TEX_RECT:
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
g_clear_pointer (&op->coords, g_array_unref);
|
||||
if (op->multitex_coords != NULL)
|
||||
g_array_unref (op->multitex_coords);
|
||||
break;
|
||||
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
@ -808,36 +810,6 @@ clutter_paint_op_init_tex_rect (ClutterPaintOperation *op,
|
||||
op->op.texrect[7] = y_2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_paint_op_init_tex_rects (ClutterPaintOperation *op,
|
||||
const float *coords,
|
||||
unsigned int n_rects,
|
||||
gboolean use_default_tex_coords)
|
||||
{
|
||||
const unsigned int n_floats = n_rects * 8;
|
||||
|
||||
clutter_paint_operation_clear (op);
|
||||
|
||||
op->opcode = PAINT_OP_TEX_RECTS;
|
||||
op->coords = g_array_sized_new (FALSE, FALSE, sizeof (float), n_floats);
|
||||
|
||||
if (use_default_tex_coords)
|
||||
{
|
||||
const float default_tex_coords[4] = { 0.0, 0.0, 1.0, 1.0 };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
g_array_append_vals (op->coords, &coords[i * 4], 4);
|
||||
g_array_append_vals (op->coords, default_tex_coords, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_array_append_vals (op->coords, coords, n_floats);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
|
||||
const ClutterActorBox *rect,
|
||||
@ -847,11 +819,11 @@ clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
|
||||
clutter_paint_operation_clear (op);
|
||||
|
||||
op->opcode = PAINT_OP_MULTITEX_RECT;
|
||||
op->coords = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (float),
|
||||
tex_coords_len);
|
||||
op->multitex_coords = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (float),
|
||||
tex_coords_len);
|
||||
|
||||
g_array_append_vals (op->coords, tex_coords, tex_coords_len);
|
||||
g_array_append_vals (op->multitex_coords, tex_coords, tex_coords_len);
|
||||
|
||||
op->op.texrect[0] = rect->x1;
|
||||
op->op.texrect[1] = rect->y1;
|
||||
@ -963,74 +935,6 @@ clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node,
|
||||
g_array_append_val (node->operations, operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_add_rectangles:
|
||||
* @node: a #ClutterPaintNode
|
||||
* @coords: (in) (array length=n_rects) (transfer none): array of
|
||||
* coordinates containing groups of 4 float values: [x_1, y_1, x_2, y_2] that
|
||||
* are interpreted as two position coordinates; one for the top left of the
|
||||
* rectangle (x1, y1), and one for the bottom right of the rectangle
|
||||
* (x2, y2).
|
||||
* @n_rects: number of rectangles defined in @coords.
|
||||
*
|
||||
* Adds a series of rectangles to @node.
|
||||
*
|
||||
* As a general rule for better performance its recommended to use this API
|
||||
* instead of calling clutter_paint_node_add_rectangle() separately for
|
||||
* multiple rectangles if all of the rectangles will be drawn together.
|
||||
*
|
||||
* See cogl_framebuffer_draw_rectangles().
|
||||
*/
|
||||
void
|
||||
clutter_paint_node_add_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects)
|
||||
{
|
||||
ClutterPaintOperation operation = PAINT_OP_INIT;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
|
||||
g_return_if_fail (coords != NULL);
|
||||
|
||||
clutter_paint_node_maybe_init_operations (node);
|
||||
|
||||
clutter_paint_op_init_tex_rects (&operation, coords, n_rects, TRUE);
|
||||
g_array_append_val (node->operations, operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_add_texture_rectangles:
|
||||
* @node: a #ClutterPaintNode
|
||||
* @coords: (in) (array length=n_rects) (transfer none): array containing
|
||||
* groups of 8 float values: [x_1, y_1, x_2, y_2, s_1, t_1, s_2, t_2]
|
||||
* that have the same meaning as the arguments for
|
||||
* cogl_framebuffer_draw_textured_rectangle().
|
||||
* @n_rects: number of rectangles defined in @coords.
|
||||
*
|
||||
* Adds a series of rectangles to @node.
|
||||
*
|
||||
* The given texture coordinates should always be normalized such that
|
||||
* (0, 0) corresponds to the top left and (1, 1) corresponds to the
|
||||
* bottom right. To map an entire texture across the rectangle pass
|
||||
* in s_1=0, t_1=0, s_2=1, t_2=1.
|
||||
*
|
||||
* See cogl_framebuffer_draw_textured_rectangles().
|
||||
*/
|
||||
void
|
||||
clutter_paint_node_add_texture_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects)
|
||||
{
|
||||
ClutterPaintOperation operation = PAINT_OP_INIT;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
|
||||
g_return_if_fail (coords != NULL);
|
||||
|
||||
clutter_paint_node_maybe_init_operations (node);
|
||||
|
||||
clutter_paint_op_init_tex_rects (&operation, coords, n_rects, FALSE);
|
||||
g_array_append_val (node->operations, operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_add_primitive: (skip)
|
||||
* @node: a #ClutterPaintNode
|
||||
@ -1154,26 +1058,13 @@ clutter_paint_node_to_json (ClutterPaintNode *node)
|
||||
json_builder_end_array (builder);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
json_builder_set_member_name (builder, "texrects");
|
||||
json_builder_begin_array (builder);
|
||||
|
||||
for (j = 0; i < op->coords->len; j++)
|
||||
{
|
||||
float coord = g_array_index (op->coords, float, j);
|
||||
json_builder_add_double_value (builder, coord);
|
||||
}
|
||||
|
||||
json_builder_end_array (builder);
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
json_builder_set_member_name (builder, "texrect");
|
||||
json_builder_begin_array (builder);
|
||||
|
||||
for (j = 0; i < op->coords->len; j++)
|
||||
for (j = 0; i < op->multitex_coords->len; j++)
|
||||
{
|
||||
float coord = g_array_index (op->coords, float, j);
|
||||
float coord = g_array_index (op->multitex_coords, float, j);
|
||||
json_builder_add_double_value (builder, coord);
|
||||
}
|
||||
|
||||
@ -1258,14 +1149,24 @@ _clutter_paint_node_create (GType gtype)
|
||||
return (gpointer) g_type_create_instance (gtype);
|
||||
}
|
||||
|
||||
static ClutterPaintNode *
|
||||
clutter_paint_node_get_root (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterPaintNode *iter;
|
||||
|
||||
iter = node;
|
||||
while (iter != NULL && iter->parent != NULL)
|
||||
iter = iter->parent;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_get_framebuffer:
|
||||
* @node: a #ClutterPaintNode
|
||||
*
|
||||
* Retrieves the #CoglFramebuffer that @node will draw
|
||||
* into. If @node doesn't specify a custom framebuffer,
|
||||
* the first ancestor with a custom framebuffer will be
|
||||
* used.
|
||||
* into, if it the root node has a custom framebuffer set.
|
||||
*
|
||||
* Returns: (transfer none): a #CoglFramebuffer or %NULL if no custom one is
|
||||
* set.
|
||||
@ -1273,17 +1174,12 @@ _clutter_paint_node_create (GType gtype)
|
||||
CoglFramebuffer *
|
||||
clutter_paint_node_get_framebuffer (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterPaintNode *root = clutter_paint_node_get_root (node);
|
||||
ClutterPaintNodeClass *klass;
|
||||
|
||||
while (node)
|
||||
{
|
||||
klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
|
||||
|
||||
if (klass->get_framebuffer != NULL)
|
||||
return klass->get_framebuffer (node);
|
||||
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
klass = CLUTTER_PAINT_NODE_GET_CLASS (root);
|
||||
if (klass->get_framebuffer != NULL)
|
||||
return klass->get_framebuffer (root);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -83,15 +83,6 @@ void clutter_paint_node_add_multitexture_rectangle (ClutterP
|
||||
const float *text_coords,
|
||||
unsigned int text_coords_len);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_paint_node_add_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_paint_node_add_texture_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_paint_node_add_primitive (ClutterPaintNode *node,
|
||||
CoglPrimitive *primitive);
|
||||
|
@ -33,13 +33,14 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-paint-node-private.h"
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-blur-private.h"
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
@ -129,7 +130,7 @@ clutter_root_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterRootNode *rnode = (ClutterRootNode *) node;
|
||||
|
||||
g_object_unref (rnode->framebuffer);
|
||||
cogl_object_unref (rnode->framebuffer);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_root_node_parent_class)->finalize (node);
|
||||
}
|
||||
@ -176,7 +177,7 @@ clutter_root_node_new (CoglFramebuffer *framebuffer,
|
||||
clear_color->alpha);
|
||||
cogl_color_premultiply (&res->clear_color);
|
||||
|
||||
res->framebuffer = g_object_ref (framebuffer);
|
||||
res->framebuffer = cogl_object_ref (framebuffer);
|
||||
res->clear_flags = clear_flags;
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
@ -190,7 +191,7 @@ struct _ClutterTransformNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
graphene_matrix_t transform;
|
||||
CoglMatrix transform;
|
||||
};
|
||||
|
||||
struct _ClutterTransformNodeClass
|
||||
@ -237,7 +238,7 @@ clutter_transform_node_class_init (ClutterTransformNodeClass *klass)
|
||||
static void
|
||||
clutter_transform_node_init (ClutterTransformNode *self)
|
||||
{
|
||||
graphene_matrix_init_identity (&self->transform);
|
||||
cogl_matrix_init_identity (&self->transform);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -248,13 +249,13 @@ clutter_transform_node_init (ClutterTransformNode *self)
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_transform_node_new (const graphene_matrix_t *transform)
|
||||
clutter_transform_node_new (const CoglMatrix *transform)
|
||||
{
|
||||
ClutterTransformNode *res;
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_TRANSFORM_NODE);
|
||||
if (transform)
|
||||
graphene_matrix_init_from_matrix (&res->transform, transform);
|
||||
res->transform = *transform;
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
@ -325,7 +326,7 @@ clutter_dummy_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterDummyNode *dnode = (ClutterDummyNode *) node;
|
||||
|
||||
g_clear_object (&dnode->framebuffer);
|
||||
cogl_clear_object (&dnode->framebuffer);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_dummy_node_parent_class)->finalize (node);
|
||||
}
|
||||
@ -357,7 +358,7 @@ _clutter_dummy_node_new (ClutterActor *actor,
|
||||
|
||||
dnode = (ClutterDummyNode *) res;
|
||||
dnode->actor = actor;
|
||||
dnode->framebuffer = g_object_ref (framebuffer);
|
||||
dnode->framebuffer = cogl_object_ref (framebuffer);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -465,13 +466,6 @@ clutter_pipeline_node_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[7]);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
cogl_framebuffer_draw_textured_rectangles (fb,
|
||||
pnode->pipeline,
|
||||
(float *) op->coords->data,
|
||||
op->coords->len / 8);
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
cogl_framebuffer_draw_multitextured_rectangle (fb,
|
||||
pnode->pipeline,
|
||||
@ -479,8 +473,8 @@ clutter_pipeline_node_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[2],
|
||||
op->op.texrect[3],
|
||||
(float *) op->coords->data,
|
||||
op->coords->len);
|
||||
(float*) op->multitex_coords->data,
|
||||
op->multitex_coords->len);
|
||||
break;
|
||||
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
@ -557,7 +551,7 @@ clutter_pipeline_node_init (ClutterPipelineNode *self)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pipeline_node_new:
|
||||
* clutter_pipeline_node_new: (skip)
|
||||
* @pipeline: (allow-none): a Cogl pipeline state object, or %NULL
|
||||
*
|
||||
* Creates a new #ClutterPaintNode that will use the @pipeline to
|
||||
@ -877,7 +871,6 @@ clutter_text_node_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
case PAINT_OP_INVALID:
|
||||
@ -1039,7 +1032,6 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node,
|
||||
retval = TRUE;
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
case PAINT_OP_INVALID:
|
||||
@ -1074,7 +1066,6 @@ clutter_clip_node_post_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
case PAINT_OP_INVALID:
|
||||
@ -1124,8 +1115,6 @@ struct _ClutterActorNode
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
ClutterActor *actor;
|
||||
int opacity_override;
|
||||
int saved_opacity_override;
|
||||
};
|
||||
|
||||
struct _ClutterActorNodeClass
|
||||
@ -1141,14 +1130,6 @@ clutter_actor_node_pre_draw (ClutterPaintNode *node,
|
||||
{
|
||||
ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
|
||||
|
||||
if (actor_node->opacity_override != -1)
|
||||
{
|
||||
actor_node->saved_opacity_override =
|
||||
clutter_actor_get_opacity_override (actor_node->actor);
|
||||
clutter_actor_set_opacity_override (actor_node->actor,
|
||||
actor_node->opacity_override);
|
||||
}
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (actor_node->actor, CLUTTER_IN_PAINT);
|
||||
|
||||
return TRUE;
|
||||
@ -1170,12 +1151,6 @@ clutter_actor_node_post_draw (ClutterPaintNode *node,
|
||||
ClutterActorNode *actor_node = CLUTTER_ACTOR_NODE (node);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (actor_node->actor, CLUTTER_IN_PAINT);
|
||||
|
||||
if (actor_node->opacity_override != -1)
|
||||
{
|
||||
clutter_actor_set_opacity_override (actor_node->actor,
|
||||
actor_node->saved_opacity_override);
|
||||
}
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
@ -1217,7 +1192,6 @@ clutter_actor_node_init (ClutterActorNode *self)
|
||||
/*
|
||||
* clutter_actor_node_new:
|
||||
* @actor: the actor to paint
|
||||
* @opacity: opacity to draw the actor with, or -1 to use the actor's opacity
|
||||
*
|
||||
* Creates a new #ClutterActorNode.
|
||||
*
|
||||
@ -1229,8 +1203,7 @@ clutter_actor_node_init (ClutterActorNode *self)
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_actor_node_new (ClutterActor *actor,
|
||||
int opacity)
|
||||
clutter_actor_node_new (ClutterActor *actor)
|
||||
{
|
||||
ClutterActorNode *res;
|
||||
|
||||
@ -1238,96 +1211,11 @@ clutter_actor_node_new (ClutterActor *actor,
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_ACTOR_NODE);
|
||||
res->actor = actor;
|
||||
res->opacity_override = CLAMP (opacity, -1, 255);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ClutterEffectNode
|
||||
*/
|
||||
|
||||
struct _ClutterEffectNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
ClutterEffect *effect;
|
||||
};
|
||||
|
||||
struct _ClutterEffectNodeClass
|
||||
{
|
||||
ClutterPaintNodeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterEffectNode, clutter_effect_node, CLUTTER_TYPE_PAINT_NODE)
|
||||
|
||||
static JsonNode *
|
||||
clutter_effect_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterEffectNode *effect_node = CLUTTER_EFFECT_NODE (node);
|
||||
ClutterActorMeta *effect_meta = CLUTTER_ACTOR_META (effect_node->effect);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autoptr (GString) string = NULL;
|
||||
const char *meta_name;
|
||||
|
||||
meta_name = clutter_actor_meta_get_name (effect_meta);
|
||||
|
||||
string = g_string_new (NULL);
|
||||
g_string_append (string, G_OBJECT_TYPE_NAME (effect_node->effect));
|
||||
g_string_append (string, " (");
|
||||
if (meta_name)
|
||||
g_string_append_printf (string, "\"%s\"", meta_name);
|
||||
else
|
||||
g_string_append (string, "unnamed");
|
||||
g_string_append (string, ")");
|
||||
|
||||
builder = json_builder_new ();
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "effect");
|
||||
json_builder_add_string_value (builder, string->str);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_node_class_init (ClutterEffectNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
|
||||
node_class->serialize = clutter_effect_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_node_init (ClutterEffectNode *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_effect_node_new:
|
||||
* @effect: the actor to paint
|
||||
*
|
||||
* Creates a new #ClutterEffectNode.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterEffectNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_effect_node_new (ClutterEffect *effect)
|
||||
{
|
||||
ClutterEffectNode *res;
|
||||
|
||||
g_assert (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_EFFECT_NODE);
|
||||
res->effect = effect;
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterLayerNode
|
||||
*/
|
||||
@ -1338,7 +1226,7 @@ struct _ClutterLayerNode
|
||||
|
||||
cairo_rectangle_t viewport;
|
||||
|
||||
graphene_matrix_t projection;
|
||||
CoglMatrix projection;
|
||||
|
||||
float fbo_width;
|
||||
float fbo_height;
|
||||
@ -1347,8 +1235,6 @@ struct _ClutterLayerNode
|
||||
CoglFramebuffer *offscreen;
|
||||
|
||||
guint8 opacity;
|
||||
|
||||
gboolean needs_fbo_setup : 1;
|
||||
};
|
||||
|
||||
struct _ClutterLayerNodeClass
|
||||
@ -1364,7 +1250,7 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
{
|
||||
ClutterLayerNode *lnode = (ClutterLayerNode *) node;
|
||||
CoglFramebuffer *framebuffer;
|
||||
graphene_matrix_t matrix;
|
||||
CoglMatrix matrix;
|
||||
|
||||
/* if we were unable to create an offscreen buffer for this node, then
|
||||
* we simply ignore it
|
||||
@ -1372,27 +1258,29 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
if (lnode->offscreen == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (lnode->needs_fbo_setup)
|
||||
{
|
||||
/* copy the same modelview from the current framebuffer to the one we
|
||||
* are going to use
|
||||
*/
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix);
|
||||
cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
|
||||
/* if no geometry was submitted for this node then we simply ignore it */
|
||||
if (node->operations == NULL)
|
||||
return FALSE;
|
||||
|
||||
cogl_framebuffer_set_viewport (lnode->offscreen,
|
||||
lnode->viewport.x,
|
||||
lnode->viewport.y,
|
||||
lnode->viewport.width,
|
||||
lnode->viewport.height);
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (lnode->offscreen,
|
||||
&lnode->projection);
|
||||
}
|
||||
/* copy the same modelview from the current framebuffer to the one we
|
||||
* are going to use
|
||||
*/
|
||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &matrix);
|
||||
|
||||
clutter_paint_context_push_framebuffer (paint_context, lnode->offscreen);
|
||||
|
||||
cogl_framebuffer_set_modelview_matrix (lnode->offscreen, &matrix);
|
||||
|
||||
cogl_framebuffer_set_viewport (lnode->offscreen,
|
||||
lnode->viewport.x,
|
||||
lnode->viewport.y,
|
||||
lnode->viewport.width,
|
||||
lnode->viewport.height);
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (lnode->offscreen,
|
||||
&lnode->projection);
|
||||
|
||||
/* clear out the target framebuffer */
|
||||
cogl_framebuffer_clear4f (lnode->offscreen,
|
||||
COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH,
|
||||
@ -1419,9 +1307,6 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_matrix (lnode->offscreen);
|
||||
clutter_paint_context_pop_framebuffer (paint_context);
|
||||
|
||||
if (!node->operations)
|
||||
return;
|
||||
|
||||
fb = clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
for (i = 0; i < node->operations->len; i++)
|
||||
@ -1448,13 +1333,6 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[7]);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
cogl_framebuffer_draw_textured_rectangles (fb,
|
||||
lnode->pipeline,
|
||||
(float *) op->coords->data,
|
||||
op->coords->len / 8);
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
cogl_framebuffer_draw_multitextured_rectangle (fb,
|
||||
lnode->pipeline,
|
||||
@ -1462,8 +1340,8 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[2],
|
||||
op->op.texrect[3],
|
||||
(float *) op->coords->data,
|
||||
op->coords->len);
|
||||
(float*) op->multitex_coords->data,
|
||||
op->multitex_coords->len);
|
||||
break;
|
||||
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
@ -1483,30 +1361,12 @@ clutter_layer_node_finalize (ClutterPaintNode *node)
|
||||
if (lnode->pipeline != NULL)
|
||||
cogl_object_unref (lnode->pipeline);
|
||||
|
||||
g_clear_object (&lnode->offscreen);
|
||||
if (lnode->offscreen != NULL)
|
||||
cogl_object_unref (lnode->offscreen);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
clutter_layer_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterLayerNode *layer_node = CLUTTER_LAYER_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *framebuffer_ptr = NULL;
|
||||
|
||||
builder = json_builder_new ();
|
||||
|
||||
framebuffer_ptr = g_strdup_printf ("%p", layer_node->offscreen);
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "framebuffer");
|
||||
json_builder_add_string_value (builder, framebuffer_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
|
||||
{
|
||||
@ -1516,13 +1376,12 @@ clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
|
||||
node_class->pre_draw = clutter_layer_node_pre_draw;
|
||||
node_class->post_draw = clutter_layer_node_post_draw;
|
||||
node_class->finalize = clutter_layer_node_finalize;
|
||||
node_class->serialize = clutter_layer_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layer_node_init (ClutterLayerNode *self)
|
||||
{
|
||||
graphene_matrix_init_identity (&self->projection);
|
||||
cogl_matrix_init_identity (&self->projection);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1545,427 +1404,57 @@ clutter_layer_node_init (ClutterLayerNode *self)
|
||||
* Since: 1.10
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_layer_node_new (const graphene_matrix_t *projection,
|
||||
clutter_layer_node_new (const CoglMatrix *projection,
|
||||
const cairo_rectangle_t *viewport,
|
||||
float width,
|
||||
float height,
|
||||
guint8 opacity)
|
||||
{
|
||||
ClutterLayerNode *lnode;
|
||||
ClutterLayerNode *res;
|
||||
CoglContext *context;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglTexture *texture;
|
||||
CoglColor color;
|
||||
g_autoptr (CoglOffscreen) offscreen = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
lnode = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
|
||||
lnode->needs_fbo_setup = TRUE;
|
||||
lnode->projection = *projection;
|
||||
lnode->viewport = *viewport;
|
||||
lnode->fbo_width = width;
|
||||
lnode->fbo_height = height;
|
||||
lnode->opacity = opacity;
|
||||
res->projection = *projection;
|
||||
res->viewport = *viewport;
|
||||
res->fbo_width = width;
|
||||
res->fbo_height = height;
|
||||
res->opacity = opacity;
|
||||
|
||||
/* the texture backing the FBO */
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
tex_2d = cogl_texture_2d_new_with_size (context,
|
||||
MAX (lnode->fbo_width, 1),
|
||||
MAX (lnode->fbo_height, 1));
|
||||
MAX (res->fbo_width, 1),
|
||||
MAX (res->fbo_height, 1));
|
||||
texture = COGL_TEXTURE (tex_2d);
|
||||
cogl_texture_set_premultiplied (texture, TRUE);
|
||||
|
||||
offscreen = cogl_offscreen_new_with_texture (texture);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
|
||||
res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture));
|
||||
if (res->offscreen == NULL)
|
||||
{
|
||||
g_warning ("Unable to create an allocate paint node offscreen: %s",
|
||||
error->message);
|
||||
cogl_object_unref (texture);
|
||||
return NULL;
|
||||
g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lnode->offscreen = COGL_FRAMEBUFFER (g_steal_pointer (&offscreen));
|
||||
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
|
||||
/* the pipeline used to paint the texture; we use nearest
|
||||
* interpolation filters because the texture is always
|
||||
* going to be painted at a 1:1 texel:pixel ratio
|
||||
*/
|
||||
lnode->pipeline = cogl_pipeline_copy (default_texture_pipeline);
|
||||
cogl_pipeline_set_layer_filters (lnode->pipeline, 0,
|
||||
res->pipeline = cogl_pipeline_copy (default_texture_pipeline);
|
||||
cogl_pipeline_set_layer_filters (res->pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (lnode->pipeline, 0, texture);
|
||||
cogl_pipeline_set_color (lnode->pipeline, &color);
|
||||
|
||||
cogl_object_unref (texture);
|
||||
|
||||
return (ClutterPaintNode *) lnode;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layer_node_new_to_framebuffer:
|
||||
* @framebuffer: a #CoglFramebuffer
|
||||
* @pipeline: a #CoglPipeline
|
||||
*
|
||||
* Creates a new #ClutterLayerNode that will redirect drawing at
|
||||
* @framebuffer. It will then use @pipeline to paint the stored
|
||||
* operations.
|
||||
*
|
||||
* When using this constructor, the caller is reponsible for setting
|
||||
* up @framebuffer, including its modelview and projection matrices,
|
||||
* and the viewport, and the @pipeline as well.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterLayerNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_layer_node_new_to_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
ClutterLayerNode *res;
|
||||
|
||||
g_return_val_if_fail (COGL_IS_FRAMEBUFFER (framebuffer), NULL);
|
||||
g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
|
||||
res->needs_fbo_setup = FALSE;
|
||||
res->fbo_width = cogl_framebuffer_get_width (framebuffer);
|
||||
res->fbo_height = cogl_framebuffer_get_height (framebuffer);
|
||||
res->offscreen = g_object_ref (framebuffer);
|
||||
res->pipeline = cogl_pipeline_copy (pipeline);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterBlitNode
|
||||
*/
|
||||
|
||||
struct _ClutterBlitNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
CoglFramebuffer *src;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterBlitNode, clutter_blit_node, CLUTTER_TYPE_PAINT_NODE)
|
||||
|
||||
static gboolean
|
||||
clutter_blit_node_pre_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
g_autoptr (GError) error = NULL;
|
||||
CoglFramebuffer *framebuffer;
|
||||
unsigned int i;
|
||||
|
||||
if (node->operations == NULL)
|
||||
return;
|
||||
|
||||
framebuffer = get_target_framebuffer (node, paint_context);
|
||||
|
||||
for (i = 0; i < node->operations->len; i++)
|
||||
{
|
||||
const ClutterPaintOperation *op;
|
||||
float op_width, op_height;
|
||||
|
||||
op = &g_array_index (node->operations, ClutterPaintOperation, i);
|
||||
|
||||
switch (op->opcode)
|
||||
{
|
||||
case PAINT_OP_INVALID:
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECT:
|
||||
op_width = op->op.texrect[6] - op->op.texrect[4];
|
||||
op_height = op->op.texrect[7] - op->op.texrect[5];
|
||||
|
||||
cogl_blit_framebuffer (blit_node->src,
|
||||
framebuffer,
|
||||
op->op.texrect[0],
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[4],
|
||||
op->op.texrect[5],
|
||||
op_width,
|
||||
op_height,
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Error blitting framebuffers: %s", error->message);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
|
||||
g_clear_object (&blit_node->src);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_blit_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
clutter_blit_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *src_ptr = NULL;
|
||||
|
||||
src_ptr = g_strdup_printf ("%p", blit_node->src);
|
||||
|
||||
builder = json_builder_new ();
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "source");
|
||||
json_builder_add_string_value (builder, src_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_class_init (ClutterBlitNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
|
||||
node_class->pre_draw = clutter_blit_node_pre_draw;
|
||||
node_class->draw = clutter_blit_node_draw;
|
||||
node_class->finalize = clutter_blit_node_finalize;
|
||||
node_class->serialize = clutter_blit_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_init (ClutterBlitNode *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blit_node_new:
|
||||
* @src: the source #CoglFramebuffer
|
||||
*
|
||||
* Creates a new #ClutterBlitNode that blits @src into the current
|
||||
* draw framebuffer.
|
||||
*
|
||||
* You must only add rectangles using clutter_blit_node_add_blit_rectangle().
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterBlitNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_blit_node_new (CoglFramebuffer *src)
|
||||
{
|
||||
ClutterBlitNode *res;
|
||||
|
||||
g_return_val_if_fail (COGL_IS_FRAMEBUFFER (src), NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_BLIT_NODE);
|
||||
res->src = g_object_ref (src);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blit_node_add_blit_rectangle:
|
||||
* @blit_node: a #ClutterBlitNode
|
||||
* @src_x: Source x position
|
||||
* @src_y: Source y position
|
||||
* @dst_x: Destination x position
|
||||
* @dst_y: Destination y position
|
||||
* @width: Width of region to copy
|
||||
* @height: Height of region to copy
|
||||
*
|
||||
* Adds a new blit rectangle to the stack of rectangles. All the
|
||||
* constraints of cogl_blit_framebuffer() apply here.
|
||||
*/
|
||||
void
|
||||
clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BLIT_NODE (blit_node));
|
||||
|
||||
clutter_paint_node_add_texture_rectangle (CLUTTER_PAINT_NODE (blit_node),
|
||||
&(ClutterActorBox) {
|
||||
.x1 = src_x,
|
||||
.y1 = src_y,
|
||||
.x2 = src_x + width,
|
||||
.y2 = src_y + height,
|
||||
},
|
||||
dst_x,
|
||||
dst_y,
|
||||
dst_x + width,
|
||||
dst_y + height);
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterBlurNode
|
||||
*/
|
||||
|
||||
struct _ClutterBlurNode
|
||||
{
|
||||
ClutterLayerNode parent_instance;
|
||||
|
||||
ClutterBlur *blur;
|
||||
unsigned int sigma;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterBlurNode, clutter_blur_node, CLUTTER_TYPE_LAYER_NODE)
|
||||
|
||||
static void
|
||||
clutter_blur_node_post_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterPaintNodeClass *parent_class =
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_blur_node_parent_class);
|
||||
ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
|
||||
|
||||
clutter_blur_apply (blur_node->blur);
|
||||
|
||||
parent_class->post_draw (node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
|
||||
|
||||
g_clear_pointer (&blur_node->blur, clutter_blur_free);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_blur_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
clutter_blur_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *src_ptr = NULL;
|
||||
|
||||
src_ptr = g_strdup_printf ("%d", blur_node->sigma);
|
||||
|
||||
builder = json_builder_new ();
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "sigma");
|
||||
json_builder_add_string_value (builder, src_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_node_class_init (ClutterBlurNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
|
||||
node_class->post_draw = clutter_blur_node_post_draw;
|
||||
node_class->finalize = clutter_blur_node_finalize;
|
||||
node_class->serialize = clutter_blur_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_node_init (ClutterBlurNode *blur_node)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_node_new:
|
||||
* @width width of the blur layer
|
||||
* @height: height of the blur layer
|
||||
* @sigma: sigma value of the blur
|
||||
*
|
||||
* Creates a new #ClutterBlurNode.
|
||||
*
|
||||
* Children of this node will be painted inside a separate framebuffer,
|
||||
* which will be blurred and painted on the current draw framebuffer.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterBlurNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_blur_node_new (unsigned int width,
|
||||
unsigned int height,
|
||||
float sigma)
|
||||
{
|
||||
g_autoptr (CoglOffscreen) offscreen = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
ClutterLayerNode *layer_node;
|
||||
ClutterBlurNode *blur_node;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglContext *context;
|
||||
CoglTexture *texture;
|
||||
ClutterBlur *blur;
|
||||
|
||||
g_return_val_if_fail (sigma >= 0.0, NULL);
|
||||
|
||||
blur_node = _clutter_paint_node_create (CLUTTER_TYPE_BLUR_NODE);
|
||||
blur_node->sigma = sigma;
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
tex_2d = cogl_texture_2d_new_with_size (context, width, height);
|
||||
|
||||
texture = COGL_TEXTURE (tex_2d);
|
||||
cogl_texture_set_premultiplied (texture, TRUE);
|
||||
|
||||
offscreen = cogl_offscreen_new_with_texture (texture);
|
||||
cogl_object_unref (tex_2d);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
|
||||
{
|
||||
g_warning ("Unable to allocate paint node offscreen: %s",
|
||||
error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
blur = clutter_blur_new (texture, sigma);
|
||||
blur_node->blur = blur;
|
||||
|
||||
if (!blur)
|
||||
{
|
||||
g_warning ("Failed to create blur pipeline");
|
||||
goto out;
|
||||
}
|
||||
|
||||
layer_node = CLUTTER_LAYER_NODE (blur_node);
|
||||
layer_node->offscreen = COGL_FRAMEBUFFER (g_steal_pointer (&offscreen));
|
||||
layer_node->pipeline = cogl_pipeline_copy (default_texture_pipeline);
|
||||
cogl_pipeline_set_layer_filters (layer_node->pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_LINEAR,
|
||||
COGL_PIPELINE_FILTER_LINEAR);
|
||||
cogl_pipeline_set_layer_texture (layer_node->pipeline,
|
||||
0,
|
||||
clutter_blur_get_texture (blur));
|
||||
|
||||
cogl_framebuffer_orthographic (layer_node->offscreen,
|
||||
0.0, 0.0,
|
||||
width, height,
|
||||
0.0, 1.0);
|
||||
cogl_pipeline_set_layer_texture (res->pipeline, 0, texture);
|
||||
cogl_pipeline_set_color (res->pipeline, &color);
|
||||
|
||||
out:
|
||||
return (ClutterPaintNode *) blur_node;
|
||||
cogl_object_unref (texture);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
@ -160,8 +160,7 @@ CLUTTER_EXPORT
|
||||
GType clutter_actor_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor,
|
||||
int opacity);
|
||||
ClutterPaintNode * clutter_actor_node_new (ClutterActor *actor);
|
||||
|
||||
#define CLUTTER_TYPE_ROOT_NODE (clutter_root_node_get_type ())
|
||||
#define CLUTTER_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROOT_NODE, ClutterRootNode))
|
||||
@ -203,16 +202,12 @@ CLUTTER_EXPORT
|
||||
GType clutter_layer_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_layer_node_new (const graphene_matrix_t *projection,
|
||||
ClutterPaintNode * clutter_layer_node_new (const CoglMatrix *projection,
|
||||
const cairo_rectangle_t *viewport,
|
||||
float width,
|
||||
float height,
|
||||
guint8 opacity);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_layer_node_new_to_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline);
|
||||
|
||||
|
||||
#define CLUTTER_TYPE_TRANSFORM_NODE (clutter_transform_node_get_type ())
|
||||
#define CLUTTER_TRANSFORM_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_TRANSFORM_NODE, ClutterTransformNode))
|
||||
@ -233,56 +228,7 @@ CLUTTER_EXPORT
|
||||
GType clutter_transform_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_transform_node_new (const graphene_matrix_t *projection);
|
||||
|
||||
#define CLUTTER_TYPE_BLIT_NODE (clutter_blit_node_get_type ())
|
||||
#define CLUTTER_BLIT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLIT_NODE, ClutterBlitNode))
|
||||
#define CLUTTER_IS_BLIT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLIT_NODE))
|
||||
|
||||
/*
|
||||
* ClutterBlitNode:
|
||||
*
|
||||
* The #ClutterBlitNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*/
|
||||
typedef struct _ClutterBlitNode ClutterBlitNode;
|
||||
typedef struct _ClutterPaintNodeClass ClutterBlitNodeClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_blit_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_blit_node_new (CoglFramebuffer *src);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
#define CLUTTER_TYPE_BLUR_NODE (clutter_blur_node_get_type ())
|
||||
#define CLUTTER_BLUR_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLUR_NODE, ClutterBlurNode))
|
||||
#define CLUTTER_IS_BLUR_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLUR_NODE))
|
||||
|
||||
/**
|
||||
* ClutterBlurNode:
|
||||
*
|
||||
* The #ClutterBurNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*/
|
||||
typedef struct _ClutterBlurNode ClutterBlurNode;
|
||||
typedef struct _ClutterLayerNodeClass ClutterBlurNodeClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_blur_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_blur_node_new (unsigned int width,
|
||||
unsigned int height,
|
||||
float sigma);
|
||||
ClutterPaintNode * clutter_transform_node_new (const CoglMatrix *projection);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -62,7 +62,7 @@ struct _ClutterPaintVolume
|
||||
|
||||
/* As an optimization for internally managed PaintVolumes we allow
|
||||
* initializing ClutterPaintVolume variables allocated on the stack
|
||||
* so we can avoid hammering the memory allocator. */
|
||||
* so we can avoid hammering the slice allocator. */
|
||||
guint is_static:1;
|
||||
|
||||
/* A newly initialized PaintVolume is considered empty as it is
|
||||
@ -85,8 +85,8 @@ struct _ClutterPaintVolume
|
||||
* TRUE) */
|
||||
guint is_2d:1;
|
||||
|
||||
/* Set to TRUE initially but cleared if the paint volume is
|
||||
* transformed by a matrix. */
|
||||
/* Set to TRUE initialy but cleared if the paint volume is
|
||||
* transfomed by a matrix. */
|
||||
guint is_axis_aligned:1;
|
||||
|
||||
|
||||
@ -111,20 +111,20 @@ void _clutter_paint_volume_set_from_volume (ClutterPaintVolu
|
||||
const ClutterPaintVolume *src);
|
||||
|
||||
void _clutter_paint_volume_complete (ClutterPaintVolume *pv);
|
||||
void _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *matrix);
|
||||
void _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection,
|
||||
const float *viewport);
|
||||
void _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
const CoglMatrix *matrix);
|
||||
void _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport);
|
||||
void _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv,
|
||||
ClutterActorBox *box);
|
||||
void _clutter_paint_volume_axis_align (ClutterPaintVolume *pv);
|
||||
void _clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv,
|
||||
ClutterActor *actor);
|
||||
|
||||
ClutterCullResult _clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const graphene_frustum_t *frustum);
|
||||
ClutterCullResult _clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const ClutterPlane *planes);
|
||||
|
||||
void _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
|
||||
ClutterStage *stage,
|
||||
@ -133,9 +133,6 @@ void _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolu
|
||||
void _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
|
||||
ClutterActor *relative_to_ancestor);
|
||||
|
||||
void clutter_paint_volume_to_box (ClutterPaintVolume *pv,
|
||||
graphene_box_t *box);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PAINT_VOLUME_PRIVATE_H__ */
|
||||
|
@ -59,7 +59,7 @@ _clutter_paint_volume_new (ClutterActor *actor)
|
||||
|
||||
g_return_val_if_fail (actor != NULL, NULL);
|
||||
|
||||
pv = g_new0 (ClutterPaintVolume, 1);
|
||||
pv = g_slice_new (ClutterPaintVolume);
|
||||
|
||||
pv->actor = actor;
|
||||
|
||||
@ -78,7 +78,7 @@ _clutter_paint_volume_new (ClutterActor *actor)
|
||||
* traversal of a Clutter scene graph and since paint volumes often
|
||||
* have a very short life cycle that maps well to stack allocation we
|
||||
* allow initializing a static ClutterPaintVolume variable to avoid
|
||||
* hammering the memory allocator.
|
||||
* hammering the slice allocator.
|
||||
*
|
||||
* We were seeing slice allocation take about 1% cumulative CPU time
|
||||
* for some very simple clutter tests which although it isn't a *lot*
|
||||
@ -133,7 +133,7 @@ clutter_paint_volume_copy (const ClutterPaintVolume *pv)
|
||||
|
||||
g_return_val_if_fail (pv != NULL, NULL);
|
||||
|
||||
copy = g_memdup2 (pv, sizeof (ClutterPaintVolume));
|
||||
copy = g_slice_dup (ClutterPaintVolume, pv);
|
||||
copy->is_static = FALSE;
|
||||
|
||||
return copy;
|
||||
@ -164,7 +164,7 @@ clutter_paint_volume_free (ClutterPaintVolume *pv)
|
||||
if (G_LIKELY (pv->is_static))
|
||||
return;
|
||||
|
||||
g_free (pv);
|
||||
g_slice_free (ClutterPaintVolume, pv);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -533,11 +533,6 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
|
||||
const ClutterPaintVolume *another_pv)
|
||||
{
|
||||
ClutterPaintVolume aligned_pv;
|
||||
graphene_point3d_t min;
|
||||
graphene_point3d_t max;
|
||||
graphene_box_t another_box;
|
||||
graphene_box_t union_box;
|
||||
graphene_box_t box;
|
||||
|
||||
g_return_if_fail (pv != NULL);
|
||||
g_return_if_fail (another_pv != NULL);
|
||||
@ -545,6 +540,9 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
|
||||
/* Both volumes have to belong to the same local coordinate space */
|
||||
g_return_if_fail (pv->actor == another_pv->actor);
|
||||
|
||||
/* NB: we only have to update vertices 0, 1, 3 and 4
|
||||
* (See the ClutterPaintVolume typedef for more details) */
|
||||
|
||||
/* We special case empty volumes because otherwise we'd end up
|
||||
* calculating a bounding box that would enclose the origin of
|
||||
* the empty volume which isn't desired.
|
||||
@ -561,34 +559,78 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
|
||||
if (!pv->is_axis_aligned)
|
||||
_clutter_paint_volume_axis_align (pv);
|
||||
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
if (!another_pv->is_axis_aligned || !another_pv->is_complete)
|
||||
if (!another_pv->is_axis_aligned)
|
||||
{
|
||||
_clutter_paint_volume_copy_static (another_pv, &aligned_pv);
|
||||
_clutter_paint_volume_axis_align (&aligned_pv);
|
||||
_clutter_paint_volume_complete (&aligned_pv);
|
||||
another_pv = &aligned_pv;
|
||||
}
|
||||
|
||||
if (G_LIKELY (pv->is_2d))
|
||||
graphene_box_init_from_points (&box, 4, pv->vertices);
|
||||
else
|
||||
graphene_box_init_from_points (&box, 8, pv->vertices);
|
||||
/* grow left*/
|
||||
/* left vertices 0, 3, 4, 7 */
|
||||
if (another_pv->vertices[0].x < pv->vertices[0].x)
|
||||
{
|
||||
int min_x = another_pv->vertices[0].x;
|
||||
pv->vertices[0].x = min_x;
|
||||
pv->vertices[3].x = min_x;
|
||||
pv->vertices[4].x = min_x;
|
||||
/* pv->vertices[7].x = min_x; */
|
||||
}
|
||||
|
||||
if (G_LIKELY (another_pv->is_2d))
|
||||
graphene_box_init_from_points (&another_box, 4, another_pv->vertices);
|
||||
else
|
||||
graphene_box_init_from_points (&another_box, 8, another_pv->vertices);
|
||||
/* grow right */
|
||||
/* right vertices 1, 2, 5, 6 */
|
||||
if (another_pv->vertices[1].x > pv->vertices[1].x)
|
||||
{
|
||||
int max_x = another_pv->vertices[1].x;
|
||||
pv->vertices[1].x = max_x;
|
||||
/* pv->vertices[2].x = max_x; */
|
||||
/* pv->vertices[5].x = max_x; */
|
||||
/* pv->vertices[6].x = max_x; */
|
||||
}
|
||||
|
||||
graphene_box_union (&box, &another_box, &union_box);
|
||||
/* grow up */
|
||||
/* top vertices 0, 1, 4, 5 */
|
||||
if (another_pv->vertices[0].y < pv->vertices[0].y)
|
||||
{
|
||||
int min_y = another_pv->vertices[0].y;
|
||||
pv->vertices[0].y = min_y;
|
||||
pv->vertices[1].y = min_y;
|
||||
pv->vertices[4].y = min_y;
|
||||
/* pv->vertices[5].y = min_y; */
|
||||
}
|
||||
|
||||
graphene_box_get_min (&union_box, &min);
|
||||
graphene_box_get_max (&union_box, &max);
|
||||
graphene_point3d_init (&pv->vertices[0], min.x, min.y, min.z);
|
||||
graphene_point3d_init (&pv->vertices[1], max.x, min.y, min.z);
|
||||
graphene_point3d_init (&pv->vertices[3], min.x, max.y, min.z);
|
||||
graphene_point3d_init (&pv->vertices[4], min.x, min.y, max.z);
|
||||
/* grow down */
|
||||
/* bottom vertices 2, 3, 6, 7 */
|
||||
if (another_pv->vertices[3].y > pv->vertices[3].y)
|
||||
{
|
||||
int may_y = another_pv->vertices[3].y;
|
||||
/* pv->vertices[2].y = may_y; */
|
||||
pv->vertices[3].y = may_y;
|
||||
/* pv->vertices[6].y = may_y; */
|
||||
/* pv->vertices[7].y = may_y; */
|
||||
}
|
||||
|
||||
/* grow forward */
|
||||
/* front vertices 0, 1, 2, 3 */
|
||||
if (another_pv->vertices[0].z < pv->vertices[0].z)
|
||||
{
|
||||
int min_z = another_pv->vertices[0].z;
|
||||
pv->vertices[0].z = min_z;
|
||||
pv->vertices[1].z = min_z;
|
||||
/* pv->vertices[2].z = min_z; */
|
||||
pv->vertices[3].z = min_z;
|
||||
}
|
||||
|
||||
/* grow backward */
|
||||
/* back vertices 4, 5, 6, 7 */
|
||||
if (another_pv->vertices[4].z > pv->vertices[4].z)
|
||||
{
|
||||
int maz_z = another_pv->vertices[4].z;
|
||||
pv->vertices[4].z = maz_z;
|
||||
/* pv->vertices[5].z = maz_z; */
|
||||
/* pv->vertices[6].z = maz_z; */
|
||||
/* pv->vertices[7].z = maz_z; */
|
||||
}
|
||||
|
||||
if (pv->vertices[4].z == pv->vertices[0].z)
|
||||
pv->is_2d = TRUE;
|
||||
@ -766,8 +808,8 @@ _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv,
|
||||
|
||||
void
|
||||
_clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection,
|
||||
const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport)
|
||||
{
|
||||
int transform_count;
|
||||
@ -785,7 +827,7 @@ _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
}
|
||||
|
||||
/* All the vertices must be up to date, since after the projection
|
||||
* it won't be trivial to derive the other vertices. */
|
||||
* it wont be trivial to derive the other vertices. */
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
/* Most actors are 2D so we only have to transform the front 4
|
||||
@ -807,7 +849,7 @@ _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
|
||||
void
|
||||
_clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *matrix)
|
||||
const CoglMatrix *matrix)
|
||||
{
|
||||
int transform_count;
|
||||
|
||||
@ -815,16 +857,16 @@ _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
{
|
||||
gfloat w = 1;
|
||||
/* Just transform the origin */
|
||||
cogl_graphene_matrix_project_point (matrix,
|
||||
&pv->vertices[0].x,
|
||||
&pv->vertices[0].y,
|
||||
&pv->vertices[0].z,
|
||||
&w);
|
||||
cogl_matrix_transform_point (matrix,
|
||||
&pv->vertices[0].x,
|
||||
&pv->vertices[0].y,
|
||||
&pv->vertices[0].z,
|
||||
&w);
|
||||
return;
|
||||
}
|
||||
|
||||
/* All the vertices must be up to date, since after the transform
|
||||
* it won't be trivial to derive the other vertices. */
|
||||
* it wont be trivial to derive the other vertices. */
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
/* Most actors are 2D so we only have to transform the front 4
|
||||
@ -834,13 +876,13 @@ _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
else
|
||||
transform_count = 8;
|
||||
|
||||
cogl_graphene_matrix_transform_points (matrix,
|
||||
3,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
transform_count);
|
||||
cogl_matrix_transform_points (matrix,
|
||||
3,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
transform_count);
|
||||
|
||||
pv->is_axis_aligned = FALSE;
|
||||
}
|
||||
@ -1015,9 +1057,9 @@ clutter_paint_volume_set_from_allocation (ClutterPaintVolume *pv,
|
||||
}
|
||||
|
||||
/* Currently paint volumes are defined relative to a given actor, but
|
||||
* in some cases it is desirable to be able to change the actor that
|
||||
* in some cases it is desireable to be able to change the actor that
|
||||
* a volume relates too (For instance for ClutterClone actors where we
|
||||
* need to masquerade the source actors volume as the volume for the
|
||||
* need to masquarade the source actors volume as the volume for the
|
||||
* clone). */
|
||||
void
|
||||
_clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv,
|
||||
@ -1029,11 +1071,14 @@ _clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv,
|
||||
}
|
||||
|
||||
ClutterCullResult
|
||||
_clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const graphene_frustum_t *frustum)
|
||||
_clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const ClutterPlane *planes)
|
||||
{
|
||||
int vertex_count;
|
||||
graphene_box_t box;
|
||||
graphene_point3d_t *vertices = pv->vertices;
|
||||
gboolean partial = FALSE;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (pv->is_empty)
|
||||
return CLUTTER_CULL_RESULT_OUT;
|
||||
@ -1050,12 +1095,33 @@ _clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
else
|
||||
vertex_count = 8;
|
||||
|
||||
graphene_box_init_from_points (&box, vertex_count, pv->vertices);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
const ClutterPlane *plane = &planes[i];
|
||||
int out = 0;
|
||||
for (j = 0; j < vertex_count; j++)
|
||||
{
|
||||
graphene_vec3_t v;
|
||||
|
||||
if (graphene_frustum_intersects_box (frustum, &box))
|
||||
return CLUTTER_CULL_RESULT_IN;
|
||||
graphene_vec3_init (&v,
|
||||
vertices[j].x - graphene_vec3_get_x (&plane->v0),
|
||||
vertices[j].y - graphene_vec3_get_y (&plane->v0),
|
||||
vertices[j].z - graphene_vec3_get_z (&plane->v0));
|
||||
|
||||
if (graphene_vec3_dot (&plane->n, &v) < 0)
|
||||
out++;
|
||||
}
|
||||
|
||||
if (out == vertex_count)
|
||||
return CLUTTER_CULL_RESULT_OUT;
|
||||
else if (out != 0)
|
||||
partial = TRUE;
|
||||
}
|
||||
|
||||
if (partial)
|
||||
return CLUTTER_CULL_RESULT_PARTIAL;
|
||||
else
|
||||
return CLUTTER_CULL_RESULT_OUT;
|
||||
return CLUTTER_CULL_RESULT_IN;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1064,13 +1130,13 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
|
||||
ClutterActorBox *box)
|
||||
{
|
||||
ClutterPaintVolume projected_pv;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
CoglMatrix modelview;
|
||||
CoglMatrix projection;
|
||||
float viewport[4];
|
||||
|
||||
_clutter_paint_volume_copy_static (pv, &projected_pv);
|
||||
|
||||
graphene_matrix_init_identity (&modelview);
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
|
||||
/* If the paint volume isn't already in eye coordinates... */
|
||||
if (pv->actor)
|
||||
@ -1115,7 +1181,7 @@ void
|
||||
_clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
|
||||
ClutterActor *relative_to_ancestor)
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
CoglMatrix matrix;
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = pv->actor;
|
||||
@ -1124,32 +1190,10 @@ _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
|
||||
|
||||
_clutter_paint_volume_set_reference_actor (pv, relative_to_ancestor);
|
||||
|
||||
graphene_matrix_init_identity (&matrix);
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
_clutter_actor_apply_relative_transformation_matrix (actor,
|
||||
relative_to_ancestor,
|
||||
&matrix);
|
||||
|
||||
_clutter_paint_volume_transform (pv, &matrix);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_paint_volume_to_box (ClutterPaintVolume *pv,
|
||||
graphene_box_t *box)
|
||||
{
|
||||
int vertex_count;
|
||||
|
||||
if (pv->is_empty)
|
||||
{
|
||||
graphene_box_init_from_box (box, graphene_box_empty ());
|
||||
return;
|
||||
}
|
||||
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
if (G_LIKELY (pv->is_2d))
|
||||
vertex_count = 4;
|
||||
else
|
||||
vertex_count = 8;
|
||||
|
||||
graphene_box_init_from_points (box, vertex_count, pv->vertices);
|
||||
}
|
||||
|
@ -354,15 +354,12 @@ clutter_pan_action_real_pan (ClutterPanAction *self,
|
||||
gboolean is_interpolated)
|
||||
{
|
||||
gfloat dx, dy;
|
||||
graphene_matrix_t transform;
|
||||
graphene_matrix_t translate;
|
||||
ClutterMatrix transform;
|
||||
|
||||
clutter_pan_action_get_constrained_motion_delta (self, 0, &dx, &dy);
|
||||
|
||||
clutter_actor_get_child_transform (actor, &transform);
|
||||
graphene_matrix_init_translate (&translate,
|
||||
&GRAPHENE_POINT3D_INIT (dx, dy, 0.0f));
|
||||
graphene_matrix_multiply (&translate, &transform, &transform);
|
||||
cogl_matrix_translate (&transform, dx, dy, 0.0f);
|
||||
clutter_actor_set_child_transform (actor, &transform);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ clutter_path_add_node_full (ClutterPath *path,
|
||||
priv->nodes_dirty = TRUE;
|
||||
}
|
||||
|
||||
/* Helper function to make the rest of the add_* functions shorter */
|
||||
/* Helper function to make the rest of teh add_* functions shorter */
|
||||
static void
|
||||
clutter_path_add_node_helper (ClutterPath *path,
|
||||
ClutterPathNodeType type,
|
||||
@ -1446,7 +1446,7 @@ clutter_path_get_length (ClutterPath *path)
|
||||
static ClutterPathNodeFull *
|
||||
clutter_path_node_full_new (void)
|
||||
{
|
||||
return g_new0 (ClutterPathNodeFull, 1);
|
||||
return g_slice_new0 (ClutterPathNodeFull);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1455,7 +1455,7 @@ clutter_path_node_full_free (ClutterPathNodeFull *node)
|
||||
if (node->bezier)
|
||||
_clutter_bezier_free (node->bezier);
|
||||
|
||||
g_free (node);
|
||||
g_slice_free (ClutterPathNodeFull, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1471,7 +1471,7 @@ clutter_path_node_full_free (ClutterPathNodeFull *node)
|
||||
ClutterPathNode *
|
||||
clutter_path_node_copy (const ClutterPathNode *node)
|
||||
{
|
||||
return g_memdup2 (node, sizeof (ClutterPathNode));
|
||||
return g_slice_dup (ClutterPathNode, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1486,7 +1486,7 @@ void
|
||||
clutter_path_node_free (ClutterPathNode *node)
|
||||
{
|
||||
if (G_LIKELY (node))
|
||||
g_free (node);
|
||||
g_slice_free (ClutterPathNode, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1550,7 +1550,7 @@ clutter_knot_copy (const ClutterKnot *knot)
|
||||
if (G_UNLIKELY (knot == NULL))
|
||||
return NULL;
|
||||
|
||||
return g_memdup2 (knot, sizeof (ClutterKnot));
|
||||
return g_slice_dup (ClutterKnot, knot);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1565,7 +1565,7 @@ void
|
||||
clutter_knot_free (ClutterKnot *knot)
|
||||
{
|
||||
if (G_LIKELY (knot != NULL))
|
||||
g_free (knot);
|
||||
g_slice_free (ClutterKnot, knot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,19 +19,7 @@
|
||||
#define CLUTTER_PICK_CONTEXT_PRIVATE_H
|
||||
|
||||
#include "clutter-pick-context.h"
|
||||
#include "clutter-pick-stack-private.h"
|
||||
|
||||
ClutterPickContext *
|
||||
clutter_pick_context_new_for_view (ClutterStageView *view,
|
||||
ClutterPickMode mode,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray);
|
||||
|
||||
ClutterPickStack *
|
||||
clutter_pick_context_steal_stack (ClutterPickContext *pick_context);
|
||||
|
||||
gboolean
|
||||
clutter_pick_context_intersects_box (ClutterPickContext *pick_context,
|
||||
const graphene_box_t *box);
|
||||
ClutterPickContext * clutter_pick_context_new_for_view (ClutterStageView *view);
|
||||
|
||||
#endif /* CLUTTER_PICK_CONTEXT_PRIVATE_H */
|
||||
|
@ -17,18 +17,13 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-pick-context-private.h"
|
||||
|
||||
struct _ClutterPickContext
|
||||
{
|
||||
grefcount ref_count;
|
||||
|
||||
ClutterPickMode mode;
|
||||
ClutterPickStack *pick_stack;
|
||||
|
||||
graphene_ray_t ray;
|
||||
graphene_point3d_t point;
|
||||
CoglFramebuffer *framebuffer;
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context,
|
||||
@ -36,22 +31,14 @@ G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context,
|
||||
clutter_pick_context_unref)
|
||||
|
||||
ClutterPickContext *
|
||||
clutter_pick_context_new_for_view (ClutterStageView *view,
|
||||
ClutterPickMode mode,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray)
|
||||
clutter_pick_context_new_for_view (ClutterStageView *view)
|
||||
{
|
||||
ClutterPickContext *pick_context;
|
||||
CoglContext *context;
|
||||
|
||||
pick_context = g_new0 (ClutterPickContext, 1);
|
||||
g_ref_count_init (&pick_context->ref_count);
|
||||
pick_context->mode = mode;
|
||||
graphene_ray_init_from_ray (&pick_context->ray, ray);
|
||||
graphene_point3d_init_from_point (&pick_context->point, point);
|
||||
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
pick_context->pick_stack = clutter_pick_stack_new (context);
|
||||
pick_context->framebuffer =
|
||||
cogl_object_ref (clutter_stage_view_get_framebuffer (view));
|
||||
|
||||
return pick_context;
|
||||
}
|
||||
@ -66,7 +53,7 @@ clutter_pick_context_ref (ClutterPickContext *pick_context)
|
||||
static void
|
||||
clutter_pick_context_dispose (ClutterPickContext *pick_context)
|
||||
{
|
||||
g_clear_pointer (&pick_context->pick_stack, clutter_pick_stack_unref);
|
||||
g_clear_pointer (&pick_context->framebuffer, cogl_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
@ -87,113 +74,10 @@ clutter_pick_context_destroy (ClutterPickContext *pick_context)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_get_mode: (skip)
|
||||
* clutter_pick_context_get_framebuffer: (skip)
|
||||
*/
|
||||
ClutterPickMode
|
||||
clutter_pick_context_get_mode (ClutterPickContext *pick_context)
|
||||
CoglFramebuffer *
|
||||
clutter_pick_context_get_framebuffer (ClutterPickContext *pick_context)
|
||||
{
|
||||
return pick_context->mode;
|
||||
}
|
||||
|
||||
ClutterPickStack *
|
||||
clutter_pick_context_steal_stack (ClutterPickContext *pick_context)
|
||||
{
|
||||
clutter_pick_stack_seal (pick_context->pick_stack);
|
||||
return g_steal_pointer (&pick_context->pick_stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_log_pick:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @box: a #ClutterActorBox
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Logs a pick rectangle into the pick stack.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_log_pick (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
clutter_pick_stack_log_pick (pick_context->pick_stack, box, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_push_clip:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Pushes a clip rectangle defined by @box into the pick stack. Pop with
|
||||
* clutter_pick_context_pop_clip() when done.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_push_clip (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box)
|
||||
{
|
||||
clutter_pick_stack_push_clip (pick_context->pick_stack, box);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_pop_clip:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
*
|
||||
* Pops the current clip rectangle from the clip stack. It is a programming
|
||||
* error to call this without a corresponding clutter_pick_context_push_clip()
|
||||
* call first.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_pop_clip (ClutterPickContext *pick_context)
|
||||
{
|
||||
clutter_pick_stack_pop_clip (pick_context->pick_stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_push_transform:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @transform: a #graphene_matrix_t
|
||||
*
|
||||
* Pushes @transform into the pick stack. Pop with
|
||||
* clutter_pick_context_pop_transform() when done.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_push_transform (ClutterPickContext *pick_context,
|
||||
const graphene_matrix_t *transform)
|
||||
{
|
||||
clutter_pick_stack_push_transform (pick_context->pick_stack, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_get_transform:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @out_matrix: (out): a #graphene_matrix_t
|
||||
*
|
||||
* Retrieves the current transform of the pick stack.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_get_transform (ClutterPickContext *pick_context,
|
||||
graphene_matrix_t *out_transform)
|
||||
{
|
||||
clutter_pick_stack_get_transform (pick_context->pick_stack, out_transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_pop_transform:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
*
|
||||
* Pops the current transform from the clip stack. It is a programming error
|
||||
* to call this without a corresponding clutter_pick_context_push_transform()
|
||||
* call first.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_pop_transform (ClutterPickContext *pick_context)
|
||||
{
|
||||
clutter_pick_stack_pop_transform (pick_context->pick_stack);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_pick_context_intersects_box (ClutterPickContext *pick_context,
|
||||
const graphene_box_t *box)
|
||||
{
|
||||
return graphene_box_contains_point (box, &pick_context->point) ||
|
||||
graphene_ray_intersects_box (&pick_context->ray, box);
|
||||
return pick_context->framebuffer;
|
||||
}
|
||||
|
@ -44,29 +44,6 @@ CLUTTER_EXPORT
|
||||
void clutter_pick_context_destroy (ClutterPickContext *pick_context);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPickMode clutter_pick_context_get_mode (ClutterPickContext *pick_context);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_log_pick (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_push_clip (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_pop_clip (ClutterPickContext *pick_context);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_push_transform (ClutterPickContext *pick_context,
|
||||
const graphene_matrix_t *transform);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_get_transform (ClutterPickContext *pick_context,
|
||||
graphene_matrix_t *out_matrix);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_pop_transform (ClutterPickContext *pick_context);
|
||||
CoglFramebuffer * clutter_pick_context_get_framebuffer (ClutterPickContext *pick_context);
|
||||
|
||||
#endif /* CLUTTER_PICK_CONTEXT_H */
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Endless OS Foundation, LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_PICK_STACK_PRIVATE_H
|
||||
#define CLUTTER_PICK_STACK_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter-macros.h"
|
||||
#include "clutter-stage-view.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_PICK_STACK (clutter_pick_stack_get_type ())
|
||||
|
||||
typedef struct _ClutterPickStack ClutterPickStack;
|
||||
|
||||
GType clutter_pick_stack_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterPickStack * clutter_pick_stack_new (CoglContext *context);
|
||||
|
||||
ClutterPickStack * clutter_pick_stack_ref (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_unref (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_seal (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_log_pick (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor);
|
||||
|
||||
void clutter_pick_stack_push_clip (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box);
|
||||
|
||||
void clutter_pick_stack_pop_clip (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_push_transform (ClutterPickStack *pick_stack,
|
||||
const graphene_matrix_t *transform);
|
||||
|
||||
void clutter_pick_stack_get_transform (ClutterPickStack *pick_stack,
|
||||
graphene_matrix_t *out_transform);
|
||||
|
||||
void clutter_pick_stack_pop_transform (ClutterPickStack *pick_stack);
|
||||
|
||||
ClutterActor *
|
||||
clutter_pick_stack_search_actor (ClutterPickStack *pick_stack,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPickStack, clutter_pick_stack_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* CLUTTER_PICK_STACK_PRIVATE_H */
|
@ -1,436 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Endless OS Foundation, LLC
|
||||
* Copyright (C) 2018 Canonical Ltd.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter-pick-stack-private.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_point3d_t vertices[4];
|
||||
CoglMatrixEntry *matrix_entry;
|
||||
ClutterActorBox rect;
|
||||
gboolean projected;
|
||||
} Record;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Record base;
|
||||
ClutterActor *actor;
|
||||
int clip_index;
|
||||
} PickRecord;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Record base;
|
||||
int prev;
|
||||
} PickClipRecord;
|
||||
|
||||
struct _ClutterPickStack
|
||||
{
|
||||
grefcount ref_count;
|
||||
|
||||
CoglMatrixStack *matrix_stack;
|
||||
GArray *vertices_stack;
|
||||
GArray *clip_stack;
|
||||
int current_clip_stack_top;
|
||||
|
||||
gboolean sealed : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterPickStack, clutter_pick_stack,
|
||||
clutter_pick_stack_ref, clutter_pick_stack_unref)
|
||||
|
||||
static void
|
||||
project_vertices (CoglMatrixEntry *matrix_entry,
|
||||
const ClutterActorBox *box,
|
||||
graphene_point3d_t vertices[4])
|
||||
{
|
||||
graphene_matrix_t m;
|
||||
int i;
|
||||
|
||||
cogl_matrix_entry_get (matrix_entry, &m);
|
||||
|
||||
graphene_point3d_init (&vertices[0], box->x1, box->y1, 0.f);
|
||||
graphene_point3d_init (&vertices[1], box->x2, box->y1, 0.f);
|
||||
graphene_point3d_init (&vertices[2], box->x2, box->y2, 0.f);
|
||||
graphene_point3d_init (&vertices[3], box->x1, box->y2, 0.f);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
float w = 1.f;
|
||||
|
||||
cogl_graphene_matrix_project_point (&m,
|
||||
&vertices[i].x,
|
||||
&vertices[i].y,
|
||||
&vertices[i].z,
|
||||
&w);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_project_record (Record *rec)
|
||||
{
|
||||
if (!rec->projected)
|
||||
{
|
||||
project_vertices (rec->matrix_entry, &rec->rect, rec->vertices);
|
||||
rec->projected = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_axis_aligned_2d_rectangle (const graphene_point3d_t vertices[4])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (!G_APPROX_VALUE (vertices[i].z,
|
||||
vertices[(i + 1) % 4].z,
|
||||
FLT_EPSILON))
|
||||
return FALSE;
|
||||
|
||||
if (!G_APPROX_VALUE (vertices[i].x,
|
||||
vertices[(i + 1) % 4].x,
|
||||
FLT_EPSILON) &&
|
||||
!G_APPROX_VALUE (vertices[i].y,
|
||||
vertices[(i + 1) % 4].y,
|
||||
FLT_EPSILON))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ray_intersects_input_region (Record *rec,
|
||||
const graphene_ray_t *ray,
|
||||
const graphene_point3d_t *point)
|
||||
{
|
||||
maybe_project_record (rec);
|
||||
|
||||
if (G_LIKELY (is_axis_aligned_2d_rectangle (rec->vertices)))
|
||||
{
|
||||
graphene_box_t box;
|
||||
graphene_box_t right_border;
|
||||
graphene_box_t bottom_border;
|
||||
|
||||
/* Graphene considers both the start and end coordinates of boxes to be
|
||||
* inclusive, while the vertices of a clutter actor are exclusive. So we
|
||||
* need to manually exclude hits on these borders
|
||||
*/
|
||||
|
||||
graphene_box_init_from_points (&box, 4, rec->vertices);
|
||||
graphene_box_init_from_points (&right_border, 2, rec->vertices + 1);
|
||||
graphene_box_init_from_points (&bottom_border, 2, rec->vertices + 2);
|
||||
|
||||
/* Fast path for actors without 3D transforms */
|
||||
if (graphene_box_contains_point (&box, point))
|
||||
{
|
||||
return !graphene_box_contains_point (&right_border, point) &&
|
||||
!graphene_box_contains_point (&bottom_border, point);
|
||||
}
|
||||
|
||||
return graphene_ray_intersects_box (ray, &box) &&
|
||||
!graphene_ray_intersects_box (ray, &right_border) &&
|
||||
!graphene_ray_intersects_box (ray, &bottom_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphene_triangle_t t0, t1;
|
||||
|
||||
/*
|
||||
* Degrade the projected quad into the following triangles:
|
||||
*
|
||||
* 0 -------------- 1
|
||||
* | • |
|
||||
* | • t0 |
|
||||
* | • |
|
||||
* | t1 • |
|
||||
* | • |
|
||||
* 3 -------------- 2
|
||||
*/
|
||||
|
||||
graphene_triangle_init_from_point3d (&t0,
|
||||
&rec->vertices[0],
|
||||
&rec->vertices[1],
|
||||
&rec->vertices[2]);
|
||||
|
||||
graphene_triangle_init_from_point3d (&t1,
|
||||
&rec->vertices[0],
|
||||
&rec->vertices[2],
|
||||
&rec->vertices[3]);
|
||||
|
||||
return graphene_triangle_contains_point (&t0, point) ||
|
||||
graphene_triangle_contains_point (&t1, point) ||
|
||||
graphene_ray_intersects_triangle (ray, &t0) ||
|
||||
graphene_ray_intersects_triangle (ray, &t1);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ray_intersects_record (ClutterPickStack *pick_stack,
|
||||
PickRecord *rec,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray)
|
||||
{
|
||||
int clip_index;
|
||||
|
||||
if (!ray_intersects_input_region (&rec->base, ray, point))
|
||||
return FALSE;
|
||||
|
||||
clip_index = rec->clip_index;
|
||||
while (clip_index >= 0)
|
||||
{
|
||||
PickClipRecord *clip =
|
||||
&g_array_index (pick_stack->clip_stack, PickClipRecord, clip_index);
|
||||
|
||||
if (!ray_intersects_input_region (&clip->base, ray, point))
|
||||
return FALSE;
|
||||
|
||||
clip_index = clip->prev;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_pick_stack_weak_refs (ClutterPickStack *pick_stack)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
|
||||
for (i = 0; i < pick_stack->vertices_stack->len; i++)
|
||||
{
|
||||
PickRecord *rec =
|
||||
&g_array_index (pick_stack->vertices_stack, PickRecord, i);
|
||||
|
||||
if (rec->actor)
|
||||
g_object_add_weak_pointer (G_OBJECT (rec->actor),
|
||||
(gpointer) &rec->actor);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_pick_stack_weak_refs (ClutterPickStack *pick_stack)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pick_stack->vertices_stack->len; i++)
|
||||
{
|
||||
PickRecord *rec =
|
||||
&g_array_index (pick_stack->vertices_stack, PickRecord, i);
|
||||
|
||||
if (rec->actor)
|
||||
g_object_remove_weak_pointer (G_OBJECT (rec->actor),
|
||||
(gpointer) &rec->actor);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_pick_stack_dispose (ClutterPickStack *pick_stack)
|
||||
{
|
||||
remove_pick_stack_weak_refs (pick_stack);
|
||||
g_clear_pointer (&pick_stack->matrix_stack, cogl_object_unref);
|
||||
g_clear_pointer (&pick_stack->vertices_stack, g_array_unref);
|
||||
g_clear_pointer (&pick_stack->clip_stack, g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_pick_record (gpointer data)
|
||||
{
|
||||
PickRecord *rec = data;
|
||||
g_clear_pointer (&rec->base.matrix_entry, cogl_matrix_entry_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_clip_record (gpointer data)
|
||||
{
|
||||
PickClipRecord *clip = data;
|
||||
g_clear_pointer (&clip->base.matrix_entry, cogl_matrix_entry_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_stack_new:
|
||||
* @context: a #CoglContext
|
||||
*
|
||||
* Creates a new #ClutterPickStack.
|
||||
*
|
||||
* Returns: (transfer full): A newly created #ClutterPickStack
|
||||
*/
|
||||
ClutterPickStack *
|
||||
clutter_pick_stack_new (CoglContext *context)
|
||||
{
|
||||
ClutterPickStack *pick_stack;
|
||||
|
||||
pick_stack = g_new0 (ClutterPickStack, 1);
|
||||
g_ref_count_init (&pick_stack->ref_count);
|
||||
pick_stack->matrix_stack = cogl_matrix_stack_new (context);
|
||||
pick_stack->vertices_stack = g_array_new (FALSE, FALSE, sizeof (PickRecord));
|
||||
pick_stack->clip_stack = g_array_new (FALSE, FALSE, sizeof (PickClipRecord));
|
||||
pick_stack->current_clip_stack_top = -1;
|
||||
|
||||
g_array_set_clear_func (pick_stack->vertices_stack, clear_pick_record);
|
||||
g_array_set_clear_func (pick_stack->clip_stack, clear_clip_record);
|
||||
|
||||
return pick_stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_stack_ref:
|
||||
* @pick_stack: A #ClutterPickStack
|
||||
*
|
||||
* Increments the reference count of @pick_stack by one.
|
||||
*
|
||||
* Returns: (transfer full): @pick_stack
|
||||
*/
|
||||
ClutterPickStack *
|
||||
clutter_pick_stack_ref (ClutterPickStack *pick_stack)
|
||||
{
|
||||
g_ref_count_inc (&pick_stack->ref_count);
|
||||
return pick_stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_stack_unref:
|
||||
* @pick_stack: A #ClutterPickStack
|
||||
*
|
||||
* Decrements the reference count of @pick_stack by one, freeing the structure
|
||||
* when the reference count reaches zero.
|
||||
*/
|
||||
void
|
||||
clutter_pick_stack_unref (ClutterPickStack *pick_stack)
|
||||
{
|
||||
if (g_ref_count_dec (&pick_stack->ref_count))
|
||||
{
|
||||
clutter_pick_stack_dispose (pick_stack);
|
||||
g_free (pick_stack);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_seal (ClutterPickStack *pick_stack)
|
||||
{
|
||||
g_assert (!pick_stack->sealed);
|
||||
add_pick_stack_weak_refs (pick_stack);
|
||||
pick_stack->sealed = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_log_pick (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
PickRecord rec;
|
||||
|
||||
g_return_if_fail (actor != NULL);
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
|
||||
rec.actor = actor;
|
||||
rec.clip_index = pick_stack->current_clip_stack_top;
|
||||
rec.base.rect = *box;
|
||||
rec.base.projected = FALSE;
|
||||
rec.base.matrix_entry = cogl_matrix_stack_get_entry (pick_stack->matrix_stack);
|
||||
cogl_matrix_entry_ref (rec.base.matrix_entry);
|
||||
|
||||
g_array_append_val (pick_stack->vertices_stack, rec);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_push_clip (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box)
|
||||
{
|
||||
PickClipRecord clip;
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
|
||||
clip.prev = pick_stack->current_clip_stack_top;
|
||||
clip.base.rect = *box;
|
||||
clip.base.projected = FALSE;
|
||||
clip.base.matrix_entry = cogl_matrix_stack_get_entry (pick_stack->matrix_stack);
|
||||
cogl_matrix_entry_ref (clip.base.matrix_entry);
|
||||
|
||||
g_array_append_val (pick_stack->clip_stack, clip);
|
||||
pick_stack->current_clip_stack_top = pick_stack->clip_stack->len - 1;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_pop_clip (ClutterPickStack *pick_stack)
|
||||
{
|
||||
const PickClipRecord *top;
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
g_assert (pick_stack->current_clip_stack_top >= 0);
|
||||
|
||||
/* Individual elements of clip_stack are not freed. This is so they can
|
||||
* be shared as part of a tree of different stacks used by different
|
||||
* actors in the pick_stack. The whole clip_stack does however get
|
||||
* freed later in clutter_pick_stack_dispose.
|
||||
*/
|
||||
|
||||
top = &g_array_index (pick_stack->clip_stack,
|
||||
PickClipRecord,
|
||||
pick_stack->current_clip_stack_top);
|
||||
|
||||
pick_stack->current_clip_stack_top = top->prev;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_push_transform (ClutterPickStack *pick_stack,
|
||||
const graphene_matrix_t *transform)
|
||||
{
|
||||
cogl_matrix_stack_push (pick_stack->matrix_stack);
|
||||
cogl_matrix_stack_multiply (pick_stack->matrix_stack, transform);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_get_transform (ClutterPickStack *pick_stack,
|
||||
graphene_matrix_t *out_transform)
|
||||
{
|
||||
cogl_matrix_stack_get (pick_stack->matrix_stack, out_transform);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_pop_transform (ClutterPickStack *pick_stack)
|
||||
{
|
||||
cogl_matrix_stack_pop (pick_stack->matrix_stack);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
clutter_pick_stack_search_actor (ClutterPickStack *pick_stack,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Search all "painted" pickable actors from front to back. A linear search
|
||||
* is required, and also performs fine since there is typically only
|
||||
* on the order of dozens of actors in the list (on screen) at a time.
|
||||
*/
|
||||
for (i = pick_stack->vertices_stack->len - 1; i >= 0; i--)
|
||||
{
|
||||
PickRecord *rec =
|
||||
&g_array_index (pick_stack->vertices_stack, PickRecord, i);
|
||||
|
||||
if (rec->actor && ray_intersects_record (pick_stack, rec, point, ray))
|
||||
return rec->actor;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
@ -44,6 +44,7 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterMainContext ClutterMainContext;
|
||||
typedef struct _ClutterVertex4 ClutterVertex4;
|
||||
|
||||
#define CLUTTER_REGISTER_VALUE_TRANSFORM_TO(TYPE_TO,func) { \
|
||||
g_value_register_transform_func (g_define_type_id, TYPE_TO, func); \
|
||||
@ -127,6 +128,8 @@ struct _ClutterMainContext
|
||||
* ordered from least recently added to most recently added */
|
||||
GList *event_filters;
|
||||
|
||||
ClutterPickMode pick_mode;
|
||||
|
||||
/* default FPS; this is only used if we cannot sync to vblank */
|
||||
guint frame_rate;
|
||||
|
||||
@ -173,8 +176,8 @@ void _clutter_threads_dispatch_free (gpointer data);
|
||||
ClutterMainContext * _clutter_context_get_default (void);
|
||||
void _clutter_context_lock (void);
|
||||
void _clutter_context_unlock (void);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_context_is_initialized (void);
|
||||
ClutterPickMode _clutter_context_get_pick_mode (void);
|
||||
gboolean _clutter_context_get_show_fps (void);
|
||||
|
||||
gboolean _clutter_feature_init (GError **error);
|
||||
@ -208,18 +211,16 @@ void _clutter_run_repaint_functions (ClutterRepaintFlags flags);
|
||||
|
||||
GType _clutter_layout_manager_get_child_meta_type (ClutterLayoutManager *manager);
|
||||
|
||||
void _clutter_util_fully_transform_vertices (const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection,
|
||||
void _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport,
|
||||
const graphene_point3d_t *vertices_in,
|
||||
graphene_point3d_t *vertices_out,
|
||||
int n_vertices);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_util_rect_from_rectangle (const cairo_rectangle_int_t *src,
|
||||
graphene_rect_t *dest);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_util_rectangle_int_extents (const graphene_rect_t *src,
|
||||
cairo_rectangle_int_t *dest);
|
||||
|
||||
@ -239,17 +240,62 @@ gboolean _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1
|
||||
gboolean clutter_util_rectangle_equal (const cairo_rectangle_int_t *src1,
|
||||
const cairo_rectangle_int_t *src2);
|
||||
|
||||
|
||||
struct _ClutterVertex4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
void
|
||||
_clutter_util_vertex4_interpolate (const ClutterVertex4 *a,
|
||||
const ClutterVertex4 *b,
|
||||
double progress,
|
||||
ClutterVertex4 *res);
|
||||
|
||||
#define CLUTTER_MATRIX_INIT_IDENTITY { \
|
||||
1.0f, 0.0f, 0.0f, 0.0f, \
|
||||
0.0f, 1.0f, 0.0f, 0.0f, \
|
||||
0.0f, 0.0f, 1.0f, 0.0f, \
|
||||
0.0f, 0.0f, 0.0f, 1.0f, \
|
||||
}
|
||||
|
||||
float _clutter_util_matrix_determinant (const ClutterMatrix *matrix);
|
||||
|
||||
void _clutter_util_matrix_skew_xy (ClutterMatrix *matrix,
|
||||
float factor);
|
||||
void _clutter_util_matrix_skew_xz (ClutterMatrix *matrix,
|
||||
float factor);
|
||||
void _clutter_util_matrix_skew_yz (ClutterMatrix *matrix,
|
||||
float factor);
|
||||
|
||||
gboolean _clutter_util_matrix_decompose (const ClutterMatrix *src,
|
||||
graphene_point3d_t *scale_p,
|
||||
float shear_p[3],
|
||||
graphene_point3d_t *rotate_p,
|
||||
graphene_point3d_t *translate_p,
|
||||
ClutterVertex4 *perspective_p);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
PangoDirection _clutter_pango_unichar_direction (gunichar ch);
|
||||
|
||||
PangoDirection _clutter_pango_find_base_dir (const gchar *text,
|
||||
gint length);
|
||||
|
||||
typedef struct _ClutterPlane
|
||||
{
|
||||
graphene_vec3_t v0;
|
||||
graphene_vec3_t n;
|
||||
} ClutterPlane;
|
||||
|
||||
typedef enum _ClutterCullResult
|
||||
{
|
||||
CLUTTER_CULL_RESULT_UNKNOWN,
|
||||
CLUTTER_CULL_RESULT_IN,
|
||||
CLUTTER_CULL_RESULT_OUT,
|
||||
CLUTTER_CULL_RESULT_PARTIAL
|
||||
} ClutterCullResult;
|
||||
|
||||
gboolean _clutter_has_progress_function (GType gtype);
|
||||
@ -261,78 +307,36 @@ gboolean _clutter_run_progress_function (GType gtype,
|
||||
|
||||
void clutter_timeline_cancel_delay (ClutterTimeline *timeline);
|
||||
|
||||
static inline void
|
||||
clutter_round_to_256ths (float *f)
|
||||
{
|
||||
*f = roundf ((*f) * 256) / 256;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ns (uint64_t ns)
|
||||
{
|
||||
return ns;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us (int64_t us)
|
||||
us (uint64_t us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
ms (int64_t ms)
|
||||
static inline uint32_t
|
||||
ms (uint32_t ms)
|
||||
{
|
||||
return ms;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
ms2us (int64_t ms)
|
||||
static inline uint64_t
|
||||
ms2us (uint64_t ms)
|
||||
{
|
||||
return us (ms * 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us2ns (int64_t us)
|
||||
static inline uint32_t
|
||||
us2ms (uint64_t us)
|
||||
{
|
||||
return ns (us * 1000);
|
||||
return (uint32_t) (us / 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us2ms (int64_t us)
|
||||
{
|
||||
return (int64_t) (us / 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
ns2us (int64_t ns)
|
||||
static inline uint64_t
|
||||
ns2us (uint64_t ns)
|
||||
{
|
||||
return us (ns / 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
s2us (int64_t s)
|
||||
{
|
||||
return s * G_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us2s (int64_t us)
|
||||
{
|
||||
return us / G_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
s2ns (int64_t s)
|
||||
{
|
||||
return us2ns (s2us (s));
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
s2ms (int64_t s)
|
||||
{
|
||||
return (int64_t) ms (s * 1000);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PRIVATE_H__ */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user