attempt to fix xwayland frac scale: 69420
Some checks failed
PikaOS Package Build & Release (amd64-v3) / build (push) Failing after 1m17s
Some checks failed
PikaOS Package Build & Release (amd64-v3) / build (push) Failing after 1m17s
This commit is contained in:
parent
58e7e76453
commit
483201997a
2
.github/release-nest-v3
vendored
2
.github/release-nest-v3
vendored
@ -1 +1 @@
|
||||
14
|
||||
15
|
||||
|
2
debian/rules
vendored
2
debian/rules
vendored
@ -4,7 +4,7 @@ include /usr/share/dpkg/default.mk
|
||||
|
||||
built_binaries := $(shell dh_listpackages)
|
||||
|
||||
export DEB_CFLAGS_MAINT_APPEND = -Wno-error -Wdeprecated-declarations
|
||||
export DEB_CFLAGS_MAINT_APPEND = -Wno-error -Wno-deprecated-declarations -Wno-unused-variable
|
||||
export DPKG_GENSYMBOLS_CHECK_LEVEL = 0
|
||||
|
||||
# Following upstream method to compute the API version
|
||||
|
2
main.sh
2
main.sh
@ -9,7 +9,7 @@ source ./pika-build-config.sh
|
||||
echo "$PIKA_BUILD_ARCH" > pika-build-arch
|
||||
|
||||
# Clone Upstream
|
||||
git clone --depth=1 https://gitlab.gnome.org/GNOME/mutter -b "$VERSION"
|
||||
#git clone --depth=1 https://gitlab.gnome.org/GNOME/mutter -b "$VERSION"
|
||||
cp -rvf ./debian ./mutter
|
||||
cd ./mutter
|
||||
|
||||
|
11
mutter/.gitignore
vendored
Normal file
11
mutter/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.swp
|
||||
*~
|
||||
**/tags.*
|
||||
subprojects/sysprof/
|
||||
__pycache__/
|
||||
.buildconfig
|
||||
.vscode
|
||||
runtime-dir
|
||||
build
|
||||
_build
|
||||
builddir
|
739
mutter/.gitlab-ci.yml
Normal file
739
mutter/.gitlab-ci.yml
Normal file
@ -0,0 +1,739 @@
|
||||
include:
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/145b1bc7ef1702d2bd71584010d7113c6786a506/templates/fedora.yml'
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/34f4ade99434043f88e164933f570301fd18b125/templates/ci-fairy.yml'
|
||||
- project: 'Infrastructure/openshift-images/gnome-release-service'
|
||||
file: '/ci-templates/release-module.yml'
|
||||
|
||||
stages:
|
||||
- review
|
||||
- prepare
|
||||
- code-review
|
||||
- build
|
||||
- test
|
||||
- analyze
|
||||
- docs
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
FDO_UPSTREAM_REPO: GNOME/mutter
|
||||
|
||||
.skip-git-clone:
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
|
||||
.mutter.git-clone:
|
||||
extends:
|
||||
- .skip-git-clone
|
||||
variables:
|
||||
MUTTER_CLONE_PATH: $CI_BUILDS_DIR/$CI_PROJECT_PATH
|
||||
MUTTER_CLONE_DEPTH: 1
|
||||
before_script: |
|
||||
if [ -n "$MUTTER_CLONE_PATH" ]; then
|
||||
set -x
|
||||
uri="$CI_REPOSITORY_URL"
|
||||
if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" ]; then
|
||||
uri="$CI_MERGE_REQUEST_SOURCE_PROJECT_URL.git"
|
||||
branch="$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
|
||||
elif [ -n "$CI_COMMIT_TAG" ]; then
|
||||
branch="$CI_COMMIT_TAG"
|
||||
elif [ -n "$CI_COMMIT_BRANCH" ]; then
|
||||
branch="$CI_COMMIT_BRANCH"
|
||||
else
|
||||
branch="$CI_DEFAULT_BRANCH"
|
||||
fi
|
||||
if [ ! -d "$MUTTER_CLONE_PATH" ] || [ -z "$(ls -A "$MUTTER_CLONE_PATH")" ]; then
|
||||
git clone --depth $MUTTER_CLONE_DEPTH "$uri" "$MUTTER_CLONE_PATH" -b "$branch"
|
||||
elif [ ! -d "$MUTTER_CLONE_PATH/.git" ]; then
|
||||
git clone --bare --depth $MUTTER_CLONE_DEPTH "$uri" "$MUTTER_CLONE_PATH/.git" -b "$branch"
|
||||
if git -C "$MUTTER_CLONE_PATH" config --unset core.bare; then
|
||||
git -C "$MUTTER_CLONE_PATH" checkout
|
||||
else
|
||||
# For some weird reasons sometimes the fast-path could fail with
|
||||
# "fatal: not in a git directory" error, so handle it manually
|
||||
tmpdir=$(mktemp --directory --tmpdir mutter-XXXXXX)
|
||||
mkdir "$tmpdir/repo"
|
||||
mv "$MUTTER_CLONE_PATH/.git" "$tmpdir/repo/"
|
||||
git clone "$tmpdir/repo" "$tmpdir/src"
|
||||
mv "$tmpdir"/src/* "$tmpdir"/src/.* "$MUTTER_CLONE_PATH"
|
||||
rm -r "$tmpdir/repo"
|
||||
rm -rv "$tmpdir"
|
||||
fi
|
||||
fi
|
||||
set +x
|
||||
fi
|
||||
|
||||
.mutter.skip-git-clone:
|
||||
extends:
|
||||
- .skip-git-clone
|
||||
variables:
|
||||
MUTTER_CLONE_PATH: ''
|
||||
|
||||
.mutter.run-as-user:
|
||||
image:
|
||||
name: ${FDO_DISTRIBUTION_IMAGE}
|
||||
entrypoint:
|
||||
- 'runuser'
|
||||
- '-u'
|
||||
- !reference [.mutter.fedora@common, variables, MUTTER_USER]
|
||||
- '--'
|
||||
|
||||
.mutter.distribution-image:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.run-as-user
|
||||
|
||||
.mutter.fedora@common:
|
||||
extends:
|
||||
- .skip-git-clone
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 40
|
||||
BASE_TAG: '2024-04-29.0'
|
||||
MUTTER_USER: 'meta-user'
|
||||
FDO_DISTRIBUTION_PACKAGES:
|
||||
asciidoc
|
||||
clang
|
||||
gcovr
|
||||
gdm
|
||||
gnome-shell
|
||||
sassc
|
||||
uncrustify
|
||||
xorg-x11-server-Xvfb
|
||||
mesa-dri-drivers
|
||||
xorg-x11-proto-devel
|
||||
qemu-system-x86-core
|
||||
busybox
|
||||
zenity
|
||||
python3-dbusmock
|
||||
"pkgconfig(libgcrypt)"
|
||||
"pkgconfig(libdisplay-info)"
|
||||
|
||||
FDO_DISTRIBUTION_EXEC: |
|
||||
set -e
|
||||
|
||||
# Create $MUTTER_USER
|
||||
useradd -u 9999 -b /opt/mutter -ms /bin/bash $MUTTER_USER
|
||||
|
||||
# Enable sudo for $MUTTER_USER
|
||||
echo "%$MUTTER_USER ALL = (ALL) NOPASSWD: ALL" > /etc/sudoers.d/99_mutter-user
|
||||
|
||||
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
|
||||
dnf builddep -y kernel --setopt=install_weak_deps=False
|
||||
dnf builddep -y gi-docgen --setopt=install_weak_deps=False
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/jadahl/catch.git \
|
||||
main
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/gi-docgen.git \
|
||||
main
|
||||
|
||||
rpm -e --nodeps gnome-bluetooth-libs-devel \
|
||||
mutter mutter-devel \
|
||||
gnome-shell
|
||||
|
||||
# Work-around for podman-push aborting on permission issue
|
||||
# https://gitlab.gnome.org/Infrastructure/Infrastructure/-/issues/1247
|
||||
rm -rf /etc/pki/pesign/
|
||||
chmod -R a+rX /opt/mutter/$MUTTER_USER
|
||||
chmod -R a+rX /var/lib/gdm
|
||||
|
||||
# Ensure that we mark the project clone dir as safe directory
|
||||
git config --system --add safe.directory "$CI_PROJECT_DIR"
|
||||
|
||||
if [[ x"$(uname -m )" = "xx86_64" ]] ; then
|
||||
if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" ]; then
|
||||
git clone --depth $MUTTER_CLONE_DEPTH \
|
||||
$CI_MERGE_REQUEST_SOURCE_PROJECT_URL.git mutter-src \
|
||||
-b "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME"
|
||||
elif [ -n "$CI_COMMIT_BRANCH" ]; then
|
||||
git clone --depth $MUTTER_CLONE_DEPTH \
|
||||
$CI_REPOSITORY_URL mutter-src -b "$CI_COMMIT_BRANCH"
|
||||
else
|
||||
git clone --depth $MUTTER_CLONE_DEPTH $CI_REPOSITORY_URL mutter-src
|
||||
fi
|
||||
meson setup build mutter-src -Dkvm_tests=true
|
||||
ninja -C build src/tests/kvm/bzImage
|
||||
mkdir -p /opt/mutter
|
||||
cp build/src/tests/kvm/bzImage /opt/mutter/bzImage
|
||||
|
||||
dnf install -y python3-argcomplete
|
||||
|
||||
git clone https://github.com/arighi/virtme-ng.git
|
||||
cd virtme-ng
|
||||
git fetch --tags
|
||||
git checkout v1.8
|
||||
./setup.py install --prefix=/usr
|
||||
cd ..
|
||||
rm -rf virtme-ng
|
||||
rm -rf build mutter-src
|
||||
fi
|
||||
retry:
|
||||
max: 2
|
||||
when:
|
||||
- 'always'
|
||||
|
||||
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@x86_64:
|
||||
extends:
|
||||
- .mutter.fedora@common
|
||||
- .mutter.git-clone
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "x86_64-${BASE_TAG}"
|
||||
|
||||
.mutter.fedora@aarch64:
|
||||
extends:
|
||||
- .mutter.fedora@common
|
||||
- .mutter.git-clone
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "aarch64-${BASE_TAG}"
|
||||
tags:
|
||||
- aarch64
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
# Allow to switch from branch pipelines to MR pipelines seamlessly
|
||||
# https://docs.gitlab.com/ee/ci/jobs/job_control.html#avoid-duplicate-pipelines
|
||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
# Don't trigger a branch pipeline if there is an open MR
|
||||
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
|
||||
.pipeline-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-]+$/'
|
||||
# Avoid catchall `when: manual` rule which might
|
||||
# cause duplicate pipelines to be triggered.
|
||||
# https://docs.gitlab.com/ee/ci/jobs/job_control.html#avoid-duplicate-pipelines
|
||||
#
|
||||
# Also make it so pipelines without MR need to be started
|
||||
# manually, since their state will most likely be WIP
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
when: 'manual'
|
||||
|
||||
.only-merge-requests:
|
||||
rules:
|
||||
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^$/'
|
||||
when: never
|
||||
- if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
when: on_success
|
||||
|
||||
repo-sanity:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: review
|
||||
variables:
|
||||
GIT_DEPTH: "1"
|
||||
script:
|
||||
- >
|
||||
if [[ -z "$CI_REGISTRY_IMAGE" ]] ;
|
||||
then
|
||||
.gitlab-ci/simple-junit-report.sh check-junit-report.xml \
|
||||
repo-sanity "The container registry should be enabled in the project general settings panel at $CI_PROJECT_URL/edit" ;
|
||||
exit 1 ;
|
||||
fi
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- check-junit-report.xml
|
||||
reports:
|
||||
junit: check-junit-report.xml
|
||||
rules:
|
||||
- !reference [.only-merge-requests, rules]
|
||||
|
||||
check-commit-log:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: review
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
script:
|
||||
ci-fairy check-commits --junit-xml=commit-message-junit-report.xml
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- commit-message-junit-report.xml
|
||||
reports:
|
||||
junit: commit-message-junit-report.xml
|
||||
rules:
|
||||
- !reference [.only-merge-requests, rules]
|
||||
|
||||
check-merge-request:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
- .skip-git-clone
|
||||
stage: review
|
||||
script:
|
||||
ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request-report.xml
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- check-merge-request-report.xml
|
||||
reports:
|
||||
junit: check-merge-request-report.xml
|
||||
rules:
|
||||
- !reference [.only-merge-requests, rules]
|
||||
|
||||
build-fedora-container@x86_64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@x86_64
|
||||
- .mutter.fedora@x86_64
|
||||
- .mutter.skip-git-clone
|
||||
stage: prepare
|
||||
rules:
|
||||
- !reference [.pipeline-guard, rules]
|
||||
|
||||
build-fedora-container@aarch64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@aarch64
|
||||
- .mutter.fedora@aarch64
|
||||
- .mutter.skip-git-clone
|
||||
stage: prepare
|
||||
rules:
|
||||
- !reference [.pipeline-guard, rules]
|
||||
when: manual
|
||||
|
||||
check-code-style:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
variables:
|
||||
MUTTER_CLONE_DEPTH: 200
|
||||
stage: code-review
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
git config --global --add safe.directory $CI_PROJECT_DIR ;
|
||||
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 ;
|
||||
allow_failure: true
|
||||
rules:
|
||||
- !reference [.only-merge-requests, rules]
|
||||
|
||||
.build-mutter-base:
|
||||
variables:
|
||||
BASE_MESON_OPTIONS:
|
||||
-Degl_device=true
|
||||
-Dwayland_eglstream=true
|
||||
-Dcatch=true
|
||||
-Dlibdisplay_info=enabled
|
||||
|
||||
.build-mutter:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .build-mutter-base
|
||||
stage: build
|
||||
script:
|
||||
- meson setup . build
|
||||
--prefix /usr
|
||||
--werror
|
||||
--fatal-meson-warnings
|
||||
--warnlevel 2
|
||||
-Dbuildtype=debugoptimized
|
||||
-Db_coverage=true
|
||||
$BASE_MESON_OPTIONS
|
||||
$EXTRA_MESON_OPTIONS
|
||||
- meson compile -C build
|
||||
- sudo meson install --dry-run -C build
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- build
|
||||
|
||||
build-mutter@x86_64:
|
||||
variables:
|
||||
EXTRA_MESON_OPTIONS:
|
||||
-Dkvm_tests=true
|
||||
-Dkvm_kernel_image=/opt/mutter/bzImage
|
||||
extends:
|
||||
- .build-mutter
|
||||
- .mutter.fedora@x86_64
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
|
||||
build-mutter@aarch64:
|
||||
extends:
|
||||
- .build-mutter
|
||||
- .mutter.fedora@aarch64
|
||||
needs:
|
||||
- job: build-fedora-container@aarch64
|
||||
artifacts: false
|
||||
when: manual
|
||||
|
||||
build-without-opengl-and-glx@x86_64:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
stage: build
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
- meson setup . build --werror --prefix /usr
|
||||
-Dbuildtype=debugoptimized
|
||||
-Dopengl=false
|
||||
-Dglx=false
|
||||
-Degl_device=true
|
||||
-Dwayland_eglstream=true
|
||||
-Dintrospection=false
|
||||
- meson compile -C build
|
||||
- sudo meson install --no-rebuild -C build
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
|
||||
build-without-native-backend-and-wayland@x86_64:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
stage: build
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
- meson setup . build --werror --prefix /usr
|
||||
-Dbuildtype=debugoptimized
|
||||
-Dnative_backend=false
|
||||
-Dudev=false
|
||||
-Dwayland=false
|
||||
-Dxwayland=false
|
||||
-Dcore_tests=false
|
||||
-Dnative_tests=false
|
||||
-Dintrospection=false
|
||||
- meson compile -C build
|
||||
- sudo meson install --no-rebuild -C build
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
|
||||
build-wayland-only@x86_64:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
stage: build
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
- meson setup . build --werror --prefix /usr
|
||||
-Dbuildtype=debugoptimized
|
||||
-Dwayland=true
|
||||
-Dxwayland=false
|
||||
-Dcore_tests=false
|
||||
-Dnative_tests=false
|
||||
-Dintrospection=false
|
||||
- meson compile -C build
|
||||
- sudo meson install --no-rebuild -C build
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
|
||||
.test-setup:
|
||||
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"
|
||||
GTK_A11Y: "none"
|
||||
before_script:
|
||||
- !reference [.mutter.git-clone, before_script]
|
||||
# Disable e.g. audio support to not dead lock screen cast tests
|
||||
- mkdir -m 700 $XDG_RUNTIME_DIR
|
||||
- pipewire & sleep 2
|
||||
|
||||
.test-mutter-base:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .test-setup
|
||||
stage: test
|
||||
after_script:
|
||||
- pushd build
|
||||
- gcovr --root=..
|
||||
--filter='\.\./src/'
|
||||
--filter='\.\./clutter/'
|
||||
--filter='\.\./cogl/'
|
||||
--filter='\.\./mtk/'
|
||||
--exclude='\.\./build/.*\.[ch]$' --exclude='.*/tests/.*\.[ch]$'
|
||||
--json --output=../coverage-${CI_JOB_NAME}.json
|
||||
- popd
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
name: "mutter-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
- coverage-*.json
|
||||
|
||||
.test-mutter:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .test-mutter-base
|
||||
script:
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
- xvfb-run -a -s "$XVFB_SERVER_ARGS"
|
||||
./src/tests/meta-dbus-runner.py
|
||||
--launch=wireplumber
|
||||
meson test
|
||||
-C build
|
||||
--setup plain
|
||||
--no-suite 'mutter/kvm'
|
||||
--no-rebuild
|
||||
--timeout-multiplier 10
|
||||
--print-errorlogs
|
||||
artifacts:
|
||||
reports:
|
||||
junit: "build/meson-logs/testlog-plain.junit.xml"
|
||||
|
||||
test-mutter@x86_64:
|
||||
extends:
|
||||
- .mutter.fedora@x86_64
|
||||
- .test-mutter
|
||||
tags:
|
||||
- asan
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
|
||||
test-mutter-kvm@x86_64:
|
||||
extends:
|
||||
- .mutter.fedora@x86_64
|
||||
- .test-mutter-base
|
||||
tags:
|
||||
- kvm
|
||||
script:
|
||||
- meson test -C build
|
||||
--no-rebuild
|
||||
--timeout-multiplier 10
|
||||
--setup plain
|
||||
--suite 'mutter/kvm'
|
||||
--print-errorlogs
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
artifacts:
|
||||
reports:
|
||||
junit: "build/meson-logs/testlog-plain.junit.xml"
|
||||
|
||||
test-mutter@aarch64:
|
||||
extends:
|
||||
- .mutter.fedora@aarch64
|
||||
- .test-mutter
|
||||
tags:
|
||||
- asan-aarch64
|
||||
needs:
|
||||
- build-mutter@aarch64
|
||||
when: manual
|
||||
|
||||
coverage:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
stage: analyze
|
||||
script:
|
||||
- mkdir coveragereport
|
||||
- gcovr --add-tracefile 'coverage-*.json'
|
||||
--html-details --print-summary --output coveragereport/index.html
|
||||
- gcovr --add-tracefile 'coverage-*.json'
|
||||
--xml --output coveragereport/coverage.xml
|
||||
artifacts:
|
||||
expose_as: 'Coverage Report'
|
||||
paths:
|
||||
- coveragereport
|
||||
- coveragereport/index.html
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
# TODO: we may need to split this file once it will reach the
|
||||
# gitlab limit size of 10M, or it will stop working:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/328772
|
||||
path: coveragereport/coverage.xml
|
||||
coverage: '/^lines: (\d+\.\d+\%)/'
|
||||
needs:
|
||||
- test-mutter@x86_64
|
||||
# - test-mutter@aarch64
|
||||
- test-mutter-kvm@x86_64
|
||||
|
||||
can-run-gnome-shell@x86_64:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
- .test-setup
|
||||
stage: test
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
before_script:
|
||||
- !reference [.mutter.fedora@x86_64, before_script]
|
||||
- sudo meson install --no-rebuild -C build
|
||||
script:
|
||||
- .gitlab-ci/checkout-gnome-shell.sh
|
||||
- meson setup gnome-shell gnome-shell/build --prefix /usr -Dbuildtype=debugoptimized -Dman=false --werror --fatal-meson-warnings
|
||||
- sudo meson install -C gnome-shell/build
|
||||
- dbus-run-session -- xvfb-run meson test -C gnome-shell/build --no-rebuild --timeout-multiplier 5
|
||||
|
||||
test-mutter-coverity:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule" && $MUTTER_SCHEDULED_JOB == "coverity"'
|
||||
when: on_success
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
when: 'manual'
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
stage: analyze
|
||||
allow_failure: true
|
||||
script:
|
||||
- .gitlab-ci/download-coverity-tarball.sh
|
||||
- CC=clang meson setup 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
|
||||
|
||||
distinfo:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora@x86_64
|
||||
- .build-mutter-base
|
||||
- .test-setup
|
||||
stage: deploy
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
- meson setup . build
|
||||
- .gitlab-ci/export-artifact-path build > dist.env
|
||||
artifacts:
|
||||
reports:
|
||||
dotenv: dist.env
|
||||
paths:
|
||||
- dist.env
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
|
||||
dist-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora@x86_64
|
||||
- .build-mutter-base
|
||||
- .test-setup
|
||||
stage: deploy
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
- meson setup . build --werror --prefix /usr
|
||||
-Dbuildtype=debugoptimized
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
- xvfb-run -a -s "$XVFB_SERVER_ARGS"
|
||||
./src/tests/meta-dbus-runner.py
|
||||
--launch=wireplumber
|
||||
meson dist -C build
|
||||
artifacts:
|
||||
expire_in: 7 day
|
||||
name: "mutter-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
|
||||
when: always
|
||||
paths:
|
||||
- build/meson-private/dist-build/meson-logs
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE != "merge_request_event"'
|
||||
when: manual
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
changes:
|
||||
- "**/meson.build"
|
||||
- meson/*
|
||||
when: on_success
|
||||
- if: '$GITLAB_USER_LOGIN == "marge-bot"'
|
||||
when: on_success
|
||||
- if: '$CI_MERGE_REQUEST_ASSIGNEES == "marge-bot"'
|
||||
when: on_success
|
||||
|
||||
dist-mutter-tarball:
|
||||
extends: dist-mutter
|
||||
needs:
|
||||
- distinfo
|
||||
artifacts:
|
||||
expose_as: 'Get tarball here'
|
||||
paths:
|
||||
- $TARBALL_ARTIFACT_PATH
|
||||
reports:
|
||||
dotenv: dist.env
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
|
||||
release-module:
|
||||
stage: deploy
|
||||
needs:
|
||||
- dist-mutter-tarball
|
||||
extends: .release-module
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
|
||||
reference:
|
||||
extends:
|
||||
- .mutter.distribution-image
|
||||
- .mutter.fedora@x86_64
|
||||
stage: docs
|
||||
needs:
|
||||
- job: build-fedora-container@x86_64
|
||||
artifacts: false
|
||||
script:
|
||||
- meson setup . build --werror -Ddocs=true -Dtests=false
|
||||
- ninja -C build
|
||||
- mkdir references
|
||||
- cp -r doc/website/* ./references
|
||||
- mv build/doc/reference/{cally/cally,clutter/clutter,cogl/cogl,cogl-pango/cogl-pango,meta/meta,mtk/mtk} references/
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
expose_as: 'Documentation'
|
||||
paths:
|
||||
- references/
|
||||
|
||||
pages:
|
||||
stage: deploy
|
||||
needs: ['reference']
|
||||
extends:
|
||||
- .skip-git-clone
|
||||
script:
|
||||
- mv references public/
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
rules:
|
||||
- if: ($CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH && $CI_PROJECT_NAMESPACE == "GNOME")
|
56
mutter/.gitlab-ci/checkout-gnome-shell.sh
Executable file
56
mutter/.gitlab-ci/checkout-gnome-shell.sh
Executable file
@ -0,0 +1,56 @@
|
||||
#!/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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd gnome-shell
|
||||
|
||||
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
|
||||
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
|
||||
ref_remote=${CI_PROJECT_URL//mutter/gnome-shell}
|
||||
echo -n Looking for $CI_COMMIT_REF_NAME on remote ...
|
||||
if fetch $ref_remote $CI_COMMIT_REF_NAME; then
|
||||
echo \ found
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
gnome_shell_target=HEAD
|
||||
echo Using $gnome_shell_target instead
|
||||
fi
|
||||
fi
|
||||
|
||||
git checkout -q $gnome_shell_target
|
19
mutter/.gitlab-ci/commit-rules.yml
Normal file
19
mutter/.gitlab-ci/commit-rules.yml
Normal file
@ -0,0 +1,19 @@
|
||||
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
|
38
mutter/.gitlab-ci/download-coverity-tarball.sh
Executable file
38
mutter/.gitlab-ci/download-coverity-tarball.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/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
|
21
mutter/.gitlab-ci/export-artifact-path
Executable file
21
mutter/.gitlab-ci/export-artifact-path
Executable file
@ -0,0 +1,21 @@
|
||||
#!/usr/bin/gjs -m
|
||||
// SPDX-FileCopyrightText: 2024 Florian Müllner <fmuellner@gnome.org>
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
import Gio from 'gi://Gio';
|
||||
import {programArgs, programInvocationName, exit} from 'system';
|
||||
|
||||
const [buildDir] = programArgs;
|
||||
if (!buildDir) {
|
||||
printerr(`usage: ${programInvocationName} <build-dir>`);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const subprocess = Gio.Subprocess.new(
|
||||
['meson', 'introspect', '--projectinfo', buildDir],
|
||||
Gio.SubprocessFlags.STDOUT_PIPE);
|
||||
const [, out] = subprocess.communicate_utf8(null, null);
|
||||
|
||||
const {descriptive_name, version} = JSON.parse(out);
|
||||
print(`TARBALL_ARTIFACT_PATH=${buildDir}/meson-dist/${descriptive_name}-${version}.tar.xz`);
|
82
mutter/.gitlab-ci/install-meson-project.sh
Executable file
82
mutter/.gitlab-ci/install-meson-project.sh
Executable file
@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
Usage: $(basename $0) [OPTION…] REPO_URL COMMIT
|
||||
|
||||
Check out and install a meson project
|
||||
|
||||
Options:
|
||||
-Dkey=val Option to pass on to meson
|
||||
--subdir Build subdirectory instead of whole project
|
||||
--prepare Script to run before build
|
||||
|
||||
-h, --help Display this help
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
TEMP=$(getopt \
|
||||
--name=$(basename $0) \
|
||||
--options='D:h' \
|
||||
--longoptions='subdir:' \
|
||||
--longoptions='prepare:' \
|
||||
--longoptions='help' \
|
||||
-- "$@")
|
||||
|
||||
eval set -- "$TEMP"
|
||||
unset TEMP
|
||||
|
||||
MESON_OPTIONS=()
|
||||
SUBDIR=.
|
||||
PREPARE=:
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
-D)
|
||||
MESON_OPTIONS+=( -D$2 )
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--subdir)
|
||||
SUBDIR=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
--prepare)
|
||||
PREPARE=$2
|
||||
shift 2
|
||||
;;
|
||||
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_URL="$1"
|
||||
COMMIT="$2"
|
||||
|
||||
CHECKOUT_DIR=$(mktemp --directory)
|
||||
trap "rm -rf $CHECKOUT_DIR" EXIT
|
||||
|
||||
git clone --depth 1 "$REPO_URL" -b "$COMMIT" "$CHECKOUT_DIR"
|
||||
|
||||
pushd "$CHECKOUT_DIR/$SUBDIR"
|
||||
sh -c "$PREPARE"
|
||||
meson setup --prefix=/usr _build "${MESON_OPTIONS[@]}"
|
||||
meson install -C _build
|
||||
popd
|
18
mutter/.gitlab-ci/simple-junit-report.sh
Executable file
18
mutter/.gitlab-ci/simple-junit-report.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
OUTFILE=$1
|
||||
NAME=$2
|
||||
MESSAGE=$3
|
||||
|
||||
cat >$OUTFILE <<EOF
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<testsuites tests="1" errors="0" failures="1">
|
||||
<testsuite name="repo-sanity" tests="1" errors="0" failures="1">
|
||||
<testcase name="$NAME" classname="repo-sanity">
|
||||
<failure message="$MESSAGE"/>
|
||||
</testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
EOF
|
||||
|
||||
# Also echo the message in stdout for good measure
|
||||
echo $MESSAGE
|
55
mutter/.gitlab/issue_templates/Bug.md
Normal file
55
mutter/.gitlab/issue_templates/Bug.md
Normal file
@ -0,0 +1,55 @@
|
||||
<!--
|
||||
Please read https://wiki.gnome.org/Community/GettingInTouch/BugReportingGuidelines
|
||||
first to ensure that you create a clear and specific issue.
|
||||
-->
|
||||
|
||||
### Affected version
|
||||
|
||||
<!--
|
||||
Provide at least the following information:
|
||||
* Your OS and version
|
||||
* Affected Mutter version
|
||||
* Does this issue appear in XOrg and/or Wayland
|
||||
-->
|
||||
|
||||
### Bug summary
|
||||
|
||||
<!--
|
||||
Provide a short summary of the bug you encountered.
|
||||
-->
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
<!--
|
||||
1. Step one
|
||||
2. Step two
|
||||
3. ...
|
||||
-->
|
||||
|
||||
### What happened
|
||||
|
||||
<!--
|
||||
What did Mutter do that was unexpected?
|
||||
-->
|
||||
|
||||
### What did you expect to happen
|
||||
|
||||
<!--
|
||||
What did you expect Mutter to do?
|
||||
-->
|
||||
|
||||
### Relevant logs, screenshots, screencasts etc.
|
||||
|
||||
<!--
|
||||
If you have further information, such as technical documentation, logs,
|
||||
screenshots or screencasts related, please provide them here.
|
||||
|
||||
If the bug is a crash, please obtain a stack trace with installed debug
|
||||
symbols (at least for GNOME Shell and Mutter) and attach it to
|
||||
this issue following the instructions on
|
||||
https://wiki.gnome.org/Community/GettingInTouch/Bugzilla/GettingTraces.
|
||||
-->
|
||||
|
||||
|
||||
<!-- Do not remove the following line. -->
|
||||
/label ~"1. Bug"
|
30
mutter/.gitlab/issue_templates/Feature.md
Normal file
30
mutter/.gitlab/issue_templates/Feature.md
Normal file
@ -0,0 +1,30 @@
|
||||
<!--
|
||||
Please read https://wiki.gnome.org/Community/GettingInTouch/BugReportingGuidelines
|
||||
first to ensure that you create a clear and specific issue.
|
||||
-->
|
||||
|
||||
### Feature summary
|
||||
|
||||
<!--
|
||||
Describe what you would like to be able to do with Mutter
|
||||
that you currently cannot do.
|
||||
-->
|
||||
|
||||
### How would you like it to work
|
||||
|
||||
<!--
|
||||
If you can think of a way Mutter might be able to do this,
|
||||
let us know here.
|
||||
-->
|
||||
|
||||
### Relevant links, screenshots, screencasts etc.
|
||||
|
||||
<!--
|
||||
If you have further information, such as technical documentation,
|
||||
code, mockups or a similar feature in another window managers,
|
||||
please provide them here.
|
||||
-->
|
||||
|
||||
|
||||
<!-- Do not remove the following line. -->
|
||||
/label ~"1. Feature"
|
339
mutter/COPYING
Normal file
339
mutter/COPYING
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
7476
mutter/NEWS
Normal file
7476
mutter/NEWS
Normal file
File diff suppressed because it is too large
Load Diff
57
mutter/README.md
Normal file
57
mutter/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# Mutter
|
||||
|
||||
Mutter is a Wayland display server and X11 window manager and compositor library.
|
||||
|
||||
When used as a Wayland display server, it runs on top of KMS and libinput. It
|
||||
implements the compositor side of the Wayland core protocol as well as various
|
||||
protocol extensions. It also has functionality related to running X11
|
||||
applications using Xwayland.
|
||||
|
||||
When used on top of Xorg it acts as a X11 window manager and compositing manager.
|
||||
|
||||
It contains functionality related to, among other things, window management,
|
||||
window compositing, focus tracking, workspace management, keybindings and
|
||||
monitor configuration.
|
||||
|
||||
Internally it uses a fork of Cogl, a hardware acceleration abstraction library
|
||||
used to simplify usage of OpenGL pipelines, as well as a fork of Clutter, a
|
||||
scene graph and user interface toolkit.
|
||||
|
||||
Mutter is used by, for example, GNOME Shell, the GNOME core user interface, and
|
||||
by Gala, elementary OS's window manager. It can also be run standalone, using
|
||||
the command "mutter", but just running plain mutter is only intended for
|
||||
debugging purposes.
|
||||
|
||||
## Contributing
|
||||
|
||||
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter.
|
||||
|
||||
It can be useful to first look at the
|
||||
[GNOME Handbook](https://handbook.gnome.org/development.html) and the
|
||||
documentation and API references below first.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Coding style and conventions](doc/coding-style.md)
|
||||
- [Git conventions](doc/git-conventions.md)
|
||||
- [Code overview](doc/code-overview.md)
|
||||
- [Building and Running](doc/building-and-running.md)
|
||||
- [Debugging](doc/debugging.md)
|
||||
- [Monitor configuration](doc/monitor-configuration.md)
|
||||
|
||||
## API Reference
|
||||
|
||||
- Meta: <https://mutter.gnome.org/meta/>
|
||||
- Clutter: <https://mutter.gnome.org/clutter/>
|
||||
- Cally: <https://mutter.gnome.org/cally/>
|
||||
- Cogl: <https://mutter.gnome.org/cogl/>
|
||||
- CoglPango: <https://mutter.gnome.org/cogl-pango/>
|
||||
- Mtk: <https://mutter.gnome.org/mtk/>
|
||||
|
||||
## License
|
||||
|
||||
Mutter is distributed under the terms of the GNU General Public License,
|
||||
version 2 or later. See the [COPYING][license] file for detalis.
|
||||
|
||||
[bug-tracker]: https://gitlab.gnome.org/GNOME/mutter/issues
|
||||
[license]: COPYING
|
164
mutter/check-style.py
Executable file
164
mutter/check-style.py
Executable file
@ -0,0 +1,164 @@
|
||||
#!/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.run(
|
||||
["git", "diff", "-U0", "--function-context", "--default-prefix", sha, "HEAD"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
encoding="utf-8",
|
||||
)
|
||||
return proc.stdout.strip().splitlines()
|
||||
|
||||
def find_chunks(diff):
|
||||
file_entry_re = re.compile(r'^\+\+\+ b/(.*)$')
|
||||
diff_chunk_re = re.compile(r'^@@ -\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()
|
||||
if start > 1:
|
||||
tmp.write(b'/** *INDENT-OFF* **/\n')
|
||||
for i, line in enumerate(f, start=1):
|
||||
if i == start - 1:
|
||||
tmp.write(b'/** *INDENT-ON* **/\n')
|
||||
|
||||
tmp.write(bytes(line, 'utf-8'))
|
||||
|
||||
if i == end - 1:
|
||||
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.run(
|
||||
["uncrustify", "-c", uncrustify_cfg, "-f", tmp.name],
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
reindented = proc.stdout.splitlines(keepends=True)
|
||||
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.run(
|
||||
["diff", "-up", "--color=always", chunk['file'], formatted.name],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
encoding="utf-8",
|
||||
)
|
||||
diff = proc.stdout
|
||||
if diff != '':
|
||||
output = re.sub('\t', '↦\t', diff)
|
||||
print(output)
|
||||
changed = True
|
||||
else:
|
||||
# Apply changes
|
||||
diff = subprocess.run(
|
||||
["diff", "-up", chunk['file'], formatted.name],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
patch = subprocess.run(["patch", chunk['file']], input=diff.stdout)
|
||||
|
||||
formatted.close()
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='Check code style. Needs uncrustify installed.')
|
||||
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.run(["git", "add", "-p"])
|
||||
if proc.returncode == 0:
|
||||
# Commit the added changes as a squash commit
|
||||
subprocess.run(
|
||||
["git", "commit", "--squash", "HEAD", "-C", "HEAD"],
|
||||
stdout=subprocess.DEVNULL)
|
||||
# Delete the unapplied changes
|
||||
subprocess.run(["git", "reset", "--hard"], stdout=subprocess.DEVNULL)
|
||||
os._exit(0)
|
||||
elif dry_run is True and changed is True:
|
||||
print(f"""
|
||||
Issue the following commands in your local tree to apply the suggested changes:
|
||||
|
||||
$ git rebase {sha} --exec "./check-style.py -r"
|
||||
$ git rebase --autosquash {sha}
|
||||
""")
|
||||
os._exit(-1)
|
||||
|
||||
os._exit(0)
|
986
mutter/clutter/clutter/cally/ChangeLog.pre-cally-merge
Normal file
986
mutter/clutter/clutter/cally/ChangeLog.pre-cally-merge
Normal file
@ -0,0 +1,986 @@
|
||||
# DO NOT MODIFY THIS FILE
|
||||
#
|
||||
# Clutter uses the Git commit log to generate the ChangeLog files when
|
||||
# creating the tarball for releases and snapshots. This file is maintained
|
||||
# only for historical reasons.
|
||||
|
||||
2010-07-05 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Cleaning ClutterText
|
||||
|
||||
* Removing superfluous g_return_if_fail
|
||||
* Removing unused ClutterText::text-changed callback
|
||||
|
||||
2010-07-05 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Refactoring "window:create" and "window:destroy" emission code
|
||||
|
||||
Previously "window:create" and "window:destroy" were emitted on
|
||||
CallyUtil. Although it works, and CallyUtil already have callbacks to
|
||||
stage_added/removed signals, I think that it is more tidy/clear to do
|
||||
that on CallyRoot:
|
||||
|
||||
* CallyRoot already has code to manage ClutterStage addition/removal
|
||||
|
||||
* In fact, we can see CallyRoot as the object exposing the a11y
|
||||
information from ClutterStageManager, so it fits better here.
|
||||
|
||||
* CallyUtil callbacks these signals are related to key event
|
||||
listeners (key snooper simulation). One of the main CallyUtil
|
||||
responsibilities is managing event (connecting, emitting), so I
|
||||
would prefer to not start to add/mix more functionalities here.
|
||||
|
||||
Ideally it would be better to emit all CallyStage methods from
|
||||
CallyStage, but it is clear that "create" and "destroy" are more easy
|
||||
to emit from a external object.
|
||||
|
||||
2010-06-25 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Cleaning clutter-actor
|
||||
|
||||
Some cleaning changes:
|
||||
* Using CallyActionFunc instead of ACTION_FUNC
|
||||
* Removing a extra * on cally-actor-private macro documentation, to
|
||||
avoid gtk-doc warnings
|
||||
* Using g_strcmp0 instead of strcmp
|
||||
|
||||
Changes to be applied on clutter (see CB#2097 and CB#2098), applied
|
||||
also here to maintain the sync. My intention is keep this developing line
|
||||
until the real integration, in order to make a final independent cally
|
||||
release.
|
||||
|
||||
2010-06-14 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Adding -Wshadow option and solving warnings related
|
||||
|
||||
|
||||
2010-06-14 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added dummy padding for future vt expansion
|
||||
|
||||
Added dummy padding on the different classes structures, to allow
|
||||
future expansion of virtual methods.
|
||||
|
||||
I decided to add this on all the classes, although it would be
|
||||
really unlikely in some cases (ie, CallyGroup)
|
||||
|
||||
2010-06-10 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Adding and emitting "window:xxx" methods on CallyStage
|
||||
|
||||
Added some window related signals on CallyStage:
|
||||
|
||||
* window:activate and window:deactivate emitted from CallyStage
|
||||
* window:create and window:destroy emitted from CallyUtil
|
||||
|
||||
ClutterStage doesn't fulfill 100% the window concept, but some of
|
||||
these signals are important in order to identify the object which
|
||||
could emit global/key events.
|
||||
|
||||
The current implementation is equivalent to GailWindow one, supposing
|
||||
CallyStage as the only window related window. This likely would change
|
||||
in any clutter-based toolkit implement a real Window object, so a more
|
||||
flexible procedure would be required. But we would solve problems step
|
||||
by step.
|
||||
|
||||
BTW: as I explain here [1] I really think that the current way to
|
||||
implement "window:xxx" signals (not defined in ATK but expected from
|
||||
the a11y implementation toolkit) somewhat hacky and undocumented (you
|
||||
need to check at-spi2 idls to know that you require to emit this
|
||||
events)
|
||||
|
||||
Related to bug CB#2147 (Orca doesn't speech out properly non
|
||||
printable chars on some environments), as solves this problem
|
||||
in a specific case.
|
||||
|
||||
[1] https://bugzilla.gnome.org/show_bug.cgi?id=620977#c1
|
||||
|
||||
2010-06-04 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Avoiding clutter_stage_get_key_focus warning
|
||||
|
||||
For any reason, in some cases, a clutter actor doesn't have a stage
|
||||
associated. We use the default one as fallback.
|
||||
|
||||
2010-06-02 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added a defunct check on cally_group_get_n_children
|
||||
|
||||
Some warnings appeared when we tried to get the number
|
||||
of children of a defunct object.
|
||||
|
||||
2010-06-02 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Update TODO file
|
||||
|
||||
Use Bugzilla to setting missing features.
|
||||
|
||||
2010-06-01 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Removing heuristics to decide CallyRectable/CallyTexture role
|
||||
|
||||
Previously CallyRectangle and CallyTexture used some heuristics in
|
||||
order to decide the default role: ATK_ROLE_IMAGE or
|
||||
ATK_PUSH_BUTTON, as in practice most applications using these
|
||||
objects as buttons were not applying the proper role.
|
||||
|
||||
As this is a hack, and a application responsibility, finally we
|
||||
have decided to remove this, so the default role is ATK_ROLE_IMAGE.
|
||||
|
||||
Fixes CB#1732 (CallyTexture and CallyRectangle uses some heuristics to
|
||||
decide the role)
|
||||
|
||||
2010-05-28 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Post-release version bump, after release 1.2.0
|
||||
|
||||
I wrongly added the last commit on the 1.1 branch, when in fact it
|
||||
requires clutter 1.3.3, and on the README it is explained that
|
||||
cally versioning is tied to clutter versioning. In order to solve
|
||||
that a clutter-1.2 release branch is created, and bumped the version.
|
||||
|
||||
This versioning tyding will be obsolete when the integration with
|
||||
clutter become a reality, but in the same way, this is the way to
|
||||
tidy this thinking in this integration.
|
||||
|
||||
2010-04-13 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Use clutter_actor_get_accessible
|
||||
|
||||
The method clutter_actor_get_accessible was added due work on
|
||||
bug 2070, and should be used to get the accessibility object,
|
||||
instead of atk_gobject_accessible_for_object
|
||||
|
||||
This would allow to implement a11y support directly on
|
||||
any clutter based toolkit object (ie StLabel).
|
||||
|
||||
2010-05-13 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added CallyClone example
|
||||
|
||||
|
||||
2010-05-13 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added a11y support for ClutterClone
|
||||
|
||||
Resolved in the most simplified way, just as a image and a
|
||||
default description to identify cloned objects.
|
||||
|
||||
More information:
|
||||
http://lists.o-hand.com/clutter/3797.html
|
||||
|
||||
2010-04-14 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Remove gail dependency
|
||||
|
||||
Removed to avoid gdk/gtk dependency on cally.
|
||||
|
||||
Part of bug CB#2072 solution
|
||||
|
||||
2010-04-14 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Avoid gdk functions filling AtkKeyEventStruct
|
||||
|
||||
Now when AtkKeyEventStruct is filled in order to emit any key event
|
||||
signal, it is not used any gdk function on the keyval or the
|
||||
string fields.
|
||||
|
||||
event_string is filled with the printable character if possible, if
|
||||
not (Ctrl, Alt, etc) it is set as NULL.
|
||||
|
||||
Now the AT should take care of that, at least until we define atk key
|
||||
event struct in a more agnostic way (not tied to gdk/gtk). See orca
|
||||
bug bgo#616206 as a example.
|
||||
|
||||
Part of bug CB#2072 solution.
|
||||
|
||||
2010-04-15 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added gail_misc_layout_get_run_attributes implementation
|
||||
|
||||
Part of bug CB#2072 solution
|
||||
|
||||
2010-04-14 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Remove gailutil/gailmisc functions calls
|
||||
|
||||
This is because gailutil/gailmisc added a gdk/gtk dependency, and
|
||||
this dependency is being removed. New cally-specific implementation
|
||||
are required.
|
||||
|
||||
Related to bug CB#1733
|
||||
|
||||
Part of bug CB#2072 solution
|
||||
|
||||
2010-04-13 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Fixing the libdir directory in some examples
|
||||
|
||||
|
||||
2010-03-26 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Previous cally.pc.in update was incomplete
|
||||
|
||||
The previous commit was not tested properly, and it was missing one
|
||||
detail. Sorry for the noise.
|
||||
|
||||
2010-03-26 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Update cally.pc.in after module relocation
|
||||
|
||||
Previous commit places cally module in a different directory.
|
||||
It also corrects where the include directory is placed.
|
||||
|
||||
2010-03-15 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Use a proper clutter module directory
|
||||
|
||||
Use a proper clutter module directory, instead of keep being
|
||||
installed on a gtk directory.
|
||||
|
||||
Improve the cally-examples-util, in order to keep using
|
||||
hardcoded values.
|
||||
|
||||
Fixes CB#1737 (Wrong cally module directory)
|
||||
|
||||
2010-03-15 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Proper UTF-8 headers
|
||||
|
||||
|
||||
2010-02-25 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Change "--with-dbus" option for "atk-bridge-dir" on examples
|
||||
|
||||
The atk-adaptor in the dbus at-spi was renamed to atk-bridge due
|
||||
some apps hardcoding the name. So right now the only difference
|
||||
is the final directory.
|
||||
|
||||
So the option was removed, and atk-bridge-dir added. This also allows
|
||||
to use the system atk-bridge or the compiled in any developing environment,
|
||||
so it is really more flexible.
|
||||
|
||||
See the README (updated with this commit) for more information.
|
||||
|
||||
2010-02-19 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added .gitignore file
|
||||
|
||||
|
||||
2010-02-19 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Release 1.1.1
|
||||
|
||||
|
||||
2010-02-19 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Using clutter_threads_idle_add instead of the gdk one
|
||||
|
||||
The idea is being as less gdk dependent as possible. Right now
|
||||
it is inviable to remove the dependency (gailutil and so on) but
|
||||
hypothetically, the ideal is remove this dependency in the future,
|
||||
and being "clutter pure".
|
||||
|
||||
2010-02-15 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Check if the state is defunct on cally_text_get_name
|
||||
|
||||
Check if the state is defunct on cally_text_get_name, in order
|
||||
to avoid warnings cally clutter_text_get_text when the clutter
|
||||
object is NULL
|
||||
|
||||
2010-01-26 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Update on configure.ac after autoupdate call
|
||||
|
||||
|
||||
2010-02-02 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Try to apply the key modifiers to event->keyval like GDK does
|
||||
|
||||
ClutterKeyEvent defines the keyval without taking into account the
|
||||
modifiers. GDK defines this keyval taking into account the modifiers.
|
||||
|
||||
AtkKeyEventStruct expects the keyval in a GDK fashion, so a
|
||||
translation is required.
|
||||
|
||||
This patch tries to do that using using
|
||||
gdk_keymap_translate_keyboard_state.
|
||||
|
||||
This functions only works correctly if gtk has been initialized, so
|
||||
the fallback is create the AtkKeyEventStruct with the keyval
|
||||
provided by Clutter.
|
||||
|
||||
More information:
|
||||
http://library.gnome.org/devel/atk/stable/AtkUtil.html#AtkKeyEventStruct
|
||||
http://bugzilla.openedhand.com/show_bug.cgi?id=1961
|
||||
|
||||
2010-02-02 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Filling AtkKeyEventStruct->string used on the atk key event listeners
|
||||
|
||||
Finally we use directly gdk_keyval_name. Not the ideal solution, but works,
|
||||
and more important, it avoids to reimplement this issue on clutter or cally.
|
||||
|
||||
More information on Bug 1952
|
||||
|
||||
Fixes http://bugzilla.openedhand.com/show_bug.cgi?id=1952
|
||||
|
||||
2010-01-22 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added AM_PROG_CC_C_O option to avoid a warning running configure
|
||||
|
||||
|
||||
2010-01-22 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Fix clutter version required on the pc files
|
||||
|
||||
|
||||
2010-01-22 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Check on configure time if any x11 clutter backend is in use
|
||||
|
||||
It uses AC_CHECK_LIB in order to check if x11 backend is in use.
|
||||
It also modifies cally-actor in order to use the information
|
||||
retrieved.
|
||||
|
||||
So now cally has a minimum multi-backend support. It only manages
|
||||
a x11 (glx or eglx) backend, but at least, it checks it, so you
|
||||
can compile cally without this backend. It probably will not work
|
||||
properly, but at least you can compile and execute it.
|
||||
|
||||
Solves http://bugzilla.openedhand.com/show_bug.cgi?id=1736
|
||||
|
||||
2010-01-21 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Fix the perspective problems computing the on-screen extensions
|
||||
|
||||
Use clutter_actor_get_abs_allocation_vertices and
|
||||
clutter_actor_get_transformed_size to get the real on-screen
|
||||
position and size, instead of compute that using the geometry
|
||||
and the anchor point.
|
||||
|
||||
It also update cally-atkcomponent-example, adding a actor inside
|
||||
a nested ClutterGroup hierarchy.
|
||||
|
||||
Fixes: http://bugzilla.openedhand.com/show_bug.cgi?id=1731
|
||||
|
||||
2010-01-13 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added extra button on cally-atkeditabletext-example
|
||||
|
||||
Added a button to print the current cursor position, and also
|
||||
extend the size of the buttons
|
||||
|
||||
2010-01-12 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Remove superfluous g_print on CallyStage
|
||||
|
||||
|
||||
2009-12-03 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Use clutter_stage_manager_peek_stages to avoid a leak
|
||||
|
||||
|
||||
2009-12-03 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added ATK_STATE_SELECTABLE_TEXT management
|
||||
|
||||
|
||||
2009-11-26 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Manage properly ATK_STATE_ACTIVE on CallyStage
|
||||
|
||||
* cally/cally-stage.c
|
||||
Added private struct
|
||||
(cally_stage_class_init),(cally_stage_init),(cally_stage_real_initialize):
|
||||
Initialization stuff
|
||||
(cally_stage_activate_cb)
|
||||
(cally_stage_deactivate_cb): new ClutterStage signal callbacks, change
|
||||
the internal value of active, and notify the atk state change
|
||||
(cally_stage_ref_state_set): manage ATK_STATE_ACTIVATE
|
||||
* examples/cally-atktext-example2.c
|
||||
If possible, creates two stage, in order to test ATK_STATE_ACTIVATE
|
||||
|
||||
2009-11-24 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Focused state change and focused object notification
|
||||
|
||||
* cally/cally-actor.h
|
||||
(focus_clutter): added virtual method for the focus management
|
||||
* cally/cally-actor.c
|
||||
(cally_actor_component_interface_init)
|
||||
(cally_actor_add_focus_handler)
|
||||
(cally_actor_remove_focus_handler):
|
||||
Implementation of the AtkComponent methods add_focus_handler and
|
||||
remove_focus_handler
|
||||
(cally_actor_focus_event): CallyActor specific focus handler, notify
|
||||
the state focused change
|
||||
(cally_actor_focus_clutter)
|
||||
(cally_actor_real_focus_clutter):
|
||||
Handlers for the ClutterActor "key-focus-in" and "key-focus-out"
|
||||
signals. Emit the signal AtkObject "focus_event" and set the focus
|
||||
object with atk_focus_tracker_notify.
|
||||
(cally_actor_initialize):
|
||||
Connect to the signals "key-focus-in" and "key-focus-out", use
|
||||
atk_component_add_focus_handler to add cally_actor_focus_event
|
||||
|
||||
Note: The focus management is more simplified that the gail one. The
|
||||
main reason is that the focus management in GTK is really more complex
|
||||
that the Clutter one.
|
||||
|
||||
2009-11-24 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Modify cally-atkeditabletext-example.c to manage "activatable" status
|
||||
|
||||
|
||||
2009-11-24 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added "activate" action in ClutterText
|
||||
|
||||
* cally/cally-actor.h
|
||||
* cally/cally-actor.c
|
||||
cally_actor_add_action now returns the action id added. Documentation
|
||||
added in order to explain the return values and others.
|
||||
|
||||
* cally/cally-text.c
|
||||
Added action "activate". This action is only available if the ClutterText is
|
||||
activatable, so the "activatable" property is tracked in the notify
|
||||
|
||||
2009-11-20 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Signal event emission
|
||||
|
||||
Emits the signals "text_selection_changed", "text_caret_moved",
|
||||
"text_changed::insert", "text_changed::delete", and notify the
|
||||
ATK_STATE_EDITABLE state change.
|
||||
|
||||
It also adds the ATK_STATE_EDITABLE in the ref_state_set, includes a
|
||||
finalize to clean the new private data used, and move part of the
|
||||
initialization from the _init to the _real_initialization.
|
||||
|
||||
2009-12-03 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Remove the ATK_STATE_DEFUNCT emission
|
||||
|
||||
Remove the ATK_STATE_DEFUNCT emission, as this is already made by
|
||||
AtkGObjectAccessible.
|
||||
|
||||
It also removes the clutter actor from the private structure, as we
|
||||
can use the AtkGObjectAccessible API to obtain it. This makes the code
|
||||
more coherent, with respect of the rest of the Cally classes
|
||||
implementation.
|
||||
|
||||
2009-11-26 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Remove ; from the CALLY_GET_CLUTTER_ACTOR macro
|
||||
|
||||
|
||||
2009-11-25 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
TODO cleanup and more implementation notes
|
||||
|
||||
* TODO: removed the data that we have in the bugzilla or in the implementation
|
||||
notes on the cally source
|
||||
* cally/cally-actor.c: complete implementations notes
|
||||
* cally/Makefile.am: add a comment related to the public headers, and include
|
||||
Makefile.in in the MAINTAINERCLEANFILES
|
||||
|
||||
2009-11-13 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Adding new tips on CODING_STYLE
|
||||
|
||||
|
||||
2009-11-09 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
AtkEditableText implementation on CallyText
|
||||
|
||||
* examples/Makefile.am
|
||||
* examples/cally-atkeditabletext-example.c: New example added
|
||||
* cally/cally-text.c
|
||||
|
||||
Interface AtkEditableText implemented, except some methods:
|
||||
* Missing ClipBoard feature on Clutter:
|
||||
paste_text
|
||||
copy_text
|
||||
cut_text
|
||||
* Missing a equivalent GtkTextTag on Clutter (so the possibility to
|
||||
set run attributes in a range):
|
||||
set_run_attributes
|
||||
|
||||
Fixes bug CB#1734
|
||||
|
||||
2009-11-03 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Removed DG_DISABLE_CHECKS and DG_DISABLE_CAST_CHECKS from CFLAGS
|
||||
|
||||
* configure.ac: Removed DG_DISABLE_CHECKS and DG_DISABLE_CAST_CHECKS
|
||||
from the common CFLAGS options
|
||||
* cally/cally-actor.c: fixed cast errors on some return values, not
|
||||
detected previously because of the use of relaxed compilation
|
||||
options
|
||||
|
||||
Problem detected by Mario Sánchez Prada <msanchez@igalia.com>
|
||||
|
||||
2009-10-28 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Support for multiple stages
|
||||
|
||||
* cally-root.c
|
||||
* cally-stage.c
|
||||
* cally-util.c
|
||||
Implemented the support for multiple stages, by tracking the signals
|
||||
stage-added and stage-removed of the ClutterStageManager.
|
||||
|
||||
In the same way CallyRoot has implement properly the atk_object_initialize,
|
||||
and in general now is more tied to ClutterStageManager (CallyRoot is now
|
||||
the a11y object of ClutterStageManager), but factory not required anyway,
|
||||
as it is instanced on the CallyUtil atk_get_root
|
||||
|
||||
Fixes: CB#1754 (Missing multi-stage support)
|
||||
|
||||
2009-10-27 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Implemented atk_[add/remove]_key_event_listener on CallyUtil
|
||||
|
||||
* cally/cally-util.c:
|
||||
Implemented atk_[add/remove]_key_event_listener
|
||||
* examples/cally-atktext-example2.c:
|
||||
Modified in order to install and remove key event listeners,
|
||||
for testing purposes
|
||||
|
||||
Fixes CB#1852 (AtkUtil implementation misses
|
||||
atk_[add/remove]_key_event_listener)
|
||||
|
||||
2009-10-21 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Implemented atk-[add/remove]-global-event-listener on CallyUtil
|
||||
|
||||
* cally/cally-util.c:
|
||||
Implemented atk-[add/remove]-global-event-listener on CallyUtil
|
||||
* examples/Makefile.am
|
||||
* examples/cally-atktext-example2.c
|
||||
New example in order to test easier the event emission on focus
|
||||
change (not working right now)
|
||||
|
||||
2009-10-12 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Add --with-dbus option executing the examples
|
||||
|
||||
The replacement for atk-bridge on at-spi-dbus has a different name
|
||||
(atk-adaptor), and it has not defined the method gnome_accessibility_init.
|
||||
The --with-dbus option allow to load the correct library and use the
|
||||
correct hook method if you are using at-spi-dbus.
|
||||
|
||||
Anyway, take into account that this is just an example, and in a final
|
||||
environment, this should be made in a more general way.
|
||||
|
||||
More information: CB#1738, CB#1737
|
||||
|
||||
2009-09-25 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Symplifying shave support.
|
||||
|
||||
|
||||
2009-09-25 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Cleanup on the compilation and installation process
|
||||
|
||||
* cally/Makefile.am:
|
||||
Added libcallydir and libcally_HEADERS in order to publish all cally
|
||||
headers, as the current policy is use the cally headers as public.
|
||||
* configure.ac:
|
||||
Change API_VERSION_MAJOR for CALLY_API_VERSION, as was the real
|
||||
meaning, and define CALLY_VERSION.
|
||||
Change CALLY_OBJ_CFLAGS and CALLY_OBJ_LIBS, used to compile the
|
||||
tests, as was not required to compile against the cally module (the
|
||||
example only required to compile against Clutter, as the cally
|
||||
module was just a module loaded by GModule).
|
||||
Support for Shave.
|
||||
|
||||
2009-07-31 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Be able to run the examples without installing Cally
|
||||
|
||||
Before that, the examples searched the cally module from the final installed
|
||||
directory. This means that you should install the library to use the examples.
|
||||
On development this is not desirable. Now it is loaded from ../cally/.libs
|
||||
|
||||
This is a little hackish, but more useful, and in the end, it is just a example.
|
||||
Probably a best option could be configure that on the command line.
|
||||
$ ./example --cally-dir="mydir"
|
||||
|
||||
But just a nitpick.
|
||||
|
||||
2009-07-29 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Upgrade to cally-1.0, using clutter-1.0
|
||||
|
||||
* NEWS
|
||||
* TODO: removed several items, waiting to be moved to the bugzilla
|
||||
* configure.ac
|
||||
* examples/cally-examples-util.c
|
||||
|
||||
2009-07-27 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Fixed return value of cally_actor_get_index_in_parent
|
||||
|
||||
Bug and solutiond pointed by Gerd Kohlberger
|
||||
|
||||
2009-06-30 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added the implementation of most AtkText methods for CluttetText (CallyText)
|
||||
|
||||
It remains some methods:
|
||||
get_default_attributes
|
||||
get_character_extents
|
||||
get_offset_at_point
|
||||
|
||||
The current gail implementation delegate on gailmisc, but this is tied to
|
||||
GtkWidget so an equivalent functionality would be implemented (something like
|
||||
callymisc), and in the case of get_character_extents, not sure about the layout
|
||||
position (see gtk_entry_get_layout_offsets).
|
||||
|
||||
I think that worth manage this in a different commit.
|
||||
|
||||
In the same way is still missing AtkEditableText support.
|
||||
|
||||
2009-07-07 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Added CALLY_GET_CLUTTER_ACTOR macro
|
||||
|
||||
This macro was created to simplify how do you get the clutter actor object
|
||||
related to the cally object. On CallyActor a private attributte maintains it
|
||||
(for convenience, as it is heavily used) but outside, atkgobject methods can
|
||||
be used. Note that there is a possibility on the future to change it. Two
|
||||
options:
|
||||
* Add a public method to get the clutter object
|
||||
* Use this method on CallyActor too
|
||||
|
||||
This macro simplifies this:
|
||||
|
||||
CLUTTER_ACTOR (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (cally_object)))
|
||||
|
||||
2009-06-24 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Renamed examples/cally-util.[ch] to examples/cally-examples-util.[ch]
|
||||
|
||||
Renamed examples/cally-util.[ch] to examples/cally-examples-util.[ch] to avoid
|
||||
confusion with cally/cally-util.[ch], implementation of the AtkUtil interface
|
||||
|
||||
2009-06-23 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Adding examples directory
|
||||
|
||||
* NEWS: Updates
|
||||
* configure.ac
|
||||
* Makefile.am
|
||||
* cally/Makefile.am
|
||||
* examples/Makefile.am: New
|
||||
* examples/cally-util.[ch]: New
|
||||
* examples/example1.c: New
|
||||
Added a directory in order to put examples. In this way we don't require any
|
||||
external clutter app to make the basic a11y functionality checks. At this
|
||||
moment only an example was added, but all the compiling structure is working.
|
||||
By default the examples are not compiled, use "--enable-examples" on configure
|
||||
time in order to enable their compilation.
|
||||
|
||||
This basic example basically shows several objects, with different depth, in
|
||||
order to check that AtkComponent returns the correct screen position.
|
||||
|
||||
Other minor changes done on the building infrastructure.
|
||||
|
||||
2009-06-23 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Fix clutter version required
|
||||
|
||||
|
||||
2009-06-23 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Solve a problem calling clutter_actor_get_anchor_point
|
||||
|
||||
* cally/cally-actor.c:
|
||||
(_get_actor_extents): use gfloat instead of gint, as now this clutter_actor_get_anchor_point
|
||||
use floats
|
||||
|
||||
2009-06-11 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Minor fixes
|
||||
|
||||
* Update TODO
|
||||
* Fix .pc files, to use clutter-0.9 version
|
||||
|
||||
2009-05-20 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Library renamed from cail to cally
|
||||
|
||||
|
||||
2009-05-08 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Removed cail-clone-texture.h from cail.h
|
||||
|
||||
* cail/cail.h: Removed reference to cail-clone-texture.h
|
||||
|
||||
2009-05-08 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Upgrade to cail-0.9, using clutter-0.9, first compilable version
|
||||
|
||||
* NEWS: new file with the information of the releases
|
||||
* TODO: updated
|
||||
* configure.ac: updated clutter version to compile against
|
||||
* cail/cail-clone-texture.[ch]: Removed as ClutterCloneTexture was removed on Clutter 0.9.0
|
||||
* cail/cail-label.[ch]: Removed as ClutterLabel was removed on Clutter 0.9.0
|
||||
* cail/Makefile.am: updated due the source files removed
|
||||
* cail/cail-actor.c: removed include to <clutter/clutter-actor.h>
|
||||
* cail/cail.c: removed the factories for CailLabel and CailCloneTexture
|
||||
|
||||
2009-05-07 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Reflect change on the version number policy
|
||||
|
||||
* README: correct some typos and explain that the cail version number
|
||||
is tied to the clutter version number and how
|
||||
* configure.ac
|
||||
Set the version number to 0.8.0
|
||||
|
||||
2009-05-07 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Edit the ChangeLog file, to show that now we are using git
|
||||
|
||||
* ChangeLog.SVN: new file, with the ChangeLog used while cail was
|
||||
using a Subversion repository
|
||||
* ChangeLog: now is empty, and only maintains a reference to use git log
|
||||
|
||||
2009-04-29 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Coding style review
|
||||
|
||||
* CODING_STYLE
|
||||
* cail/Makefile.am
|
||||
* cail/cail-actor-private.[ch]
|
||||
* cail/cail-actor.h
|
||||
* cail/cail-clone-texture.[ch]
|
||||
* cail/cail-group.[ch]
|
||||
* cail/cail-label.[ch]
|
||||
* cail/cail-rectangle.[ch]
|
||||
* cail/cail-root.[ch]
|
||||
* cail/cail-stage.[ch]
|
||||
* cail/cail-texture.[ch]
|
||||
* cail/cail-util.[ch]
|
||||
* cail/cail.c
|
||||
|
||||
2009-04-28 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Coding style review: cail-actor.c
|
||||
|
||||
|
||||
2009-04-21 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-04-21 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* TODO: updated TODO file
|
||||
|
||||
2009-04-21 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-06 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* AUTHORS: update authors file to public release
|
||||
|
||||
2009-03-06 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-06 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* debian/control
|
||||
Added cdbs dependency, renamed debugging package
|
||||
* debian/libcail-common-dbg.dirs: new file
|
||||
* debian/libcail-common.dirs
|
||||
* debian/libcail-common.install
|
||||
Minor changes
|
||||
|
||||
2009-03-05 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-05 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* TODO
|
||||
Added TODO file, in order to list the remaining tasks.
|
||||
|
||||
2009-03-05 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-05 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* configure.ac
|
||||
* cail/cail.c
|
||||
* cail/cail-util.c
|
||||
* Makefile.am
|
||||
Removed all the missing gtk related stuff
|
||||
|
||||
2009-03-05 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-05 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-actor.c
|
||||
(_get_actor_extents): managing too the anchor point to compute the position
|
||||
(_get_top_level_origin): reimplemented using x11 functions, removed
|
||||
gtk/gdk related functions, and taking into account the relative position
|
||||
inside the parent (previous position calculation was wrong if a child
|
||||
was not a direct stage child)
|
||||
* cail/clutter-gtk/cail-clutter-embed.[ch]
|
||||
* cail/clutter-gtk/cail-gtk-factory.h
|
||||
Removed, in order to remove any gtk dependency
|
||||
* cail/debian/control: removed gtk dependency
|
||||
|
||||
2009-03-03 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-03 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-actor-private.[ch]: new files to private utility functions
|
||||
(_cail_actor_pushable): new function, that checks if a cail actor is
|
||||
pushable by checking if the clutter actor related has a handler for
|
||||
a release event
|
||||
* cail/cail-texture.c
|
||||
* cail/cail-clone-texture.c
|
||||
* cail/cail-rectangle.c
|
||||
Use of new function _cail_actor_pushable
|
||||
* cail-actor.c: Added some documentation related to current implementation
|
||||
* cail-util.c: Code style review
|
||||
|
||||
2009-03-02 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-03-02 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-label.[ch]: new
|
||||
* cail/cail.[ch]
|
||||
(cail_accessibility_module_init)
|
||||
* cail/Makefile.am
|
||||
Added CailLabel, a11y object for ClutterLabel
|
||||
|
||||
2009-02-27 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-27 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-actor.c
|
||||
(cail_actor_real_remove_actor)
|
||||
Fixed a typo that causes a crash while removing the actor from a
|
||||
container
|
||||
|
||||
2009-02-26 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-26 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-actor.c
|
||||
(cail_actor_remove_actor)
|
||||
(cail_actor_add_actor)
|
||||
Fixed a typo calling klass->add_actor and klass->remove_actor that causes
|
||||
a crash in some (container,actor) combinations
|
||||
|
||||
(cail_actor_real_add_actor)
|
||||
Additional parameter check
|
||||
|
||||
2009-02-25 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
Missing cail-rectangle.[ch] files, according 2009-02-23 entry at Changelog
|
||||
|
||||
|
||||
2009-02-23 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-23 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-rectangle.[ch]
|
||||
* cail/cail.[ch]
|
||||
* cail/Makefile.am
|
||||
|
||||
Added CailRectangle, a11y object for ClutterRectangle
|
||||
|
||||
* cail/cail-group.c
|
||||
* cail/cail-texture.c
|
||||
* cail/cail-stage.c
|
||||
|
||||
Avoid to add a empty private structure, to avoid the glib warning. Anyway
|
||||
the pointer to the private structure is still on the .h, to allow future
|
||||
add-on.
|
||||
|
||||
2009-02-20 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-20 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail-actor.[ch]
|
||||
* cail-group.[ch]
|
||||
|
||||
Moved most of the ClutterContainer a11y support from cail-group to
|
||||
cail-actor, in order to generalize this support.
|
||||
|
||||
* cail-stage.[ch]
|
||||
* cail-util.[ch]
|
||||
Normalize the private structure to avoid future problems with missing
|
||||
gaps
|
||||
|
||||
2009-02-20 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-20 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-actor.c
|
||||
(cail_actor_connect_actor_destroyed): connects to the clutter actor
|
||||
destroy signal
|
||||
(cail_actor_clutter_actor_destroyed): handler to the clutter actor
|
||||
destroy signal, update the priv->actor pointer and notify a state change
|
||||
|
||||
This change allows to be sure about the priv->actor correct value, so we
|
||||
can use directly priv->actor instead of atk_gobject_accessible_get_object
|
||||
in the next functions:
|
||||
(cail_actor_get_parent)
|
||||
(cail_actor_get_index_in_parent)
|
||||
(cail_actor_ref_state_set)
|
||||
(cail_actor_get_extents)
|
||||
|
||||
2009-02-19 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-19 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-texture.[ch]
|
||||
* cail/cail-clone-texture.[ch]
|
||||
* cail/cail.[ch]
|
||||
* cail/Makefile.am
|
||||
|
||||
Added CailTexture and CailCloneTexture a11y objects for ClutterTexture
|
||||
and ClutterCloneTexture
|
||||
|
||||
* cail/cail-util.c
|
||||
|
||||
Added private structure
|
||||
|
||||
2009-02-18 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-18 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-actor.c:
|
||||
(cail_actor_get_parent)
|
||||
Return the accessible object of the clutter actor if accessible_parent
|
||||
is not available. Previously it only took into account the these object
|
||||
as a possible parent to return (you can set it with atk_object_set_parent)
|
||||
|
||||
2009-02-18 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-18 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* cail/cail-group.[ch]: code style review
|
||||
* cail/cail-actor.[ch]: implemented basic support for ClutterContainer
|
||||
|
||||
2009-02-18 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-18 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* debian/control: updating dependencies
|
||||
|
||||
2009-02-18 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-18 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* configure.ac: added additional compile flags
|
||||
* cail/cail-actor.[ch]: Reimplemented support for AtkAction interface
|
||||
* cail/cail-root.[ch]: code style review
|
||||
|
||||
2009-02-16 Alejandro Piñeiro <apinheiro@igalia.com>
|
||||
|
||||
2009-02-16 Alejandro Pinheiro <apinheiro@igalia.com>
|
||||
|
||||
* First release.
|
35
mutter/clutter/clutter/cally/cally-actor-private.h
Normal file
35
mutter/clutter/clutter/cally/cally-actor-private.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Some parts are based on GailWidget from GAIL
|
||||
* GAIL - The GNOME Accessibility Implementation Library
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cally/cally-actor.h"
|
||||
|
||||
/*
|
||||
* Auxiliary define, in order to get the clutter actor from the AtkObject using
|
||||
* AtkGObject methods
|
||||
*
|
||||
*/
|
||||
#define CALLY_GET_CLUTTER_ACTOR(cally_object) \
|
||||
(CLUTTER_ACTOR (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (cally_object))))
|
1146
mutter/clutter/clutter/cally/cally-actor.c
Normal file
1146
mutter/clutter/clutter/cally/cally-actor.c
Normal file
File diff suppressed because it is too large
Load Diff
123
mutter/clutter/clutter/cally/cally-actor.h
Normal file
123
mutter/clutter/clutter/cally/cally-actor.h
Normal file
@ -0,0 +1,123 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Some parts are based on GailWidget from GAIL
|
||||
* GAIL - The GNOME Accessibility Implementation Library
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <atk/atk.h>
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_ACTOR (cally_actor_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (CallyActor,
|
||||
cally_actor,
|
||||
CALLY,
|
||||
ACTOR,
|
||||
AtkGObjectAccessible)
|
||||
|
||||
typedef struct _CallyActor CallyActor;
|
||||
typedef struct _CallyActorClass CallyActorClass;
|
||||
typedef struct _CallyActorPrivate CallyActorPrivate;
|
||||
|
||||
/**
|
||||
* CallyActionFunc:
|
||||
* @cally_actor: a #CallyActor
|
||||
*
|
||||
* Action function, to be used on #AtkAction implementations as a individual
|
||||
* action
|
||||
*/
|
||||
typedef void (* CallyActionFunc) (CallyActor *cally_actor);
|
||||
|
||||
/**
|
||||
* CallyActionCallback:
|
||||
* @cally_actor: a #CallyActor
|
||||
* @user_data: user data passed to the function
|
||||
*
|
||||
* Action function, to be used on #AtkAction implementations as
|
||||
* an individual action.
|
||||
*
|
||||
* Unlike #CallyActionFunc, this function uses the @user_data
|
||||
* argument passed to [method@Actor.add_action_full].
|
||||
*/
|
||||
typedef void (* CallyActionCallback) (CallyActor *cally_actor,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* CallyActorClass:
|
||||
* @notify_clutter: Signal handler for notify signal on Clutter actor
|
||||
* @add_actor: Signal handler for child-added signal on Clutter actor
|
||||
* @remove_actor: Signal handler for child-removed signal on Clutter actor
|
||||
*/
|
||||
struct _CallyActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
AtkGObjectAccessibleClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (*notify_clutter) (GObject *object,
|
||||
GParamSpec *pspec);
|
||||
|
||||
gint (*add_actor) (ClutterActor *container,
|
||||
ClutterActor *actor,
|
||||
gpointer data);
|
||||
|
||||
gint (*remove_actor) (ClutterActor *container,
|
||||
ClutterActor *actor,
|
||||
gpointer data);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
AtkObject* cally_actor_new (ClutterActor *actor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint cally_actor_add_action (CallyActor *cally_actor,
|
||||
const gchar *action_name,
|
||||
const gchar *action_description,
|
||||
const gchar *action_keybinding,
|
||||
CallyActionFunc action_func);
|
||||
CLUTTER_EXPORT
|
||||
guint cally_actor_add_action_full (CallyActor *cally_actor,
|
||||
const gchar *action_name,
|
||||
const gchar *action_description,
|
||||
const gchar *action_keybinding,
|
||||
CallyActionCallback callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean cally_actor_remove_action (CallyActor *cally_actor,
|
||||
gint action_id);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean cally_actor_remove_action_by_name (CallyActor *cally_actor,
|
||||
const gchar *action_name);
|
||||
|
||||
G_END_DECLS
|
127
mutter/clutter/clutter/cally/cally-clone.c
Normal file
127
mutter/clutter/clutter/cally/cally-clone.c
Normal file
@ -0,0 +1,127 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2010 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CallyClone:
|
||||
*
|
||||
* Implementation of the ATK interfaces for a #ClutterClone
|
||||
*
|
||||
* #CallyClone implements the required ATK interfaces of [class@Clutter.Clone]
|
||||
*
|
||||
* In particular it sets a proper role for the clone, as just a image,
|
||||
* as it is the sanest and simplest approach.
|
||||
*/
|
||||
|
||||
/* Design rationale for CallyClone:
|
||||
*
|
||||
* In the old times, it was just ClutterCloneTexture. So, from a a11y POV
|
||||
* CallyCloneTexture was just another image, like ClutterTexture, and if
|
||||
* it was a clone was irrelevant. So on cally-0.8, CallyCloneTexture
|
||||
* expose a object with role ATK_ROLE_IMAGE. But now, ClutterClone is more
|
||||
* general. You can clone any object, including groups, and made things
|
||||
* like have one text entry, and a clone with different properties in the
|
||||
* same window, updated both at once.
|
||||
*
|
||||
* The question is if the idea is have a ClutterClone as a "first-class"
|
||||
* citizen inside the stage hierarchy (full clone), or it is just supposed
|
||||
* to be a mirror image of the original object.
|
||||
*
|
||||
* In the case of the a11y POV this would mean that if the text changes on
|
||||
* the source, the clone should emit as well the text-changing signals.
|
||||
*
|
||||
* As ClutterClone smartly just paint the same object with different
|
||||
* parameters, this would mean that it should be the cally object the one
|
||||
* that should replicate the source clutter hierarchy to do that,
|
||||
* something that just sound crazy.
|
||||
*
|
||||
* Taking into account that:
|
||||
*
|
||||
* - ClutterClone doesn't re-emit mirrored signals from the source
|
||||
* I think that likely the answer would be "yes, it is just a
|
||||
* mirrored image, not a real full clone".
|
||||
*
|
||||
* - You can't interact directly with the clone (ie: focus, and so on).
|
||||
* Its basic usage (right now) is clone textures.
|
||||
*
|
||||
* Any other solution could be overwhelming.
|
||||
*
|
||||
* I think that the final solution would be that ClutterClone from the
|
||||
* a11y POV should still be managed as a image (with the proper properties,
|
||||
* position, size, etc.).
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "cally/cally-clone.h"
|
||||
#include "cally/cally-actor-private.h"
|
||||
|
||||
/* AtkObject */
|
||||
static void cally_clone_real_initialize (AtkObject *obj,
|
||||
gpointer data);
|
||||
|
||||
G_DEFINE_TYPE (CallyClone, cally_clone, CALLY_TYPE_ACTOR)
|
||||
|
||||
static void
|
||||
cally_clone_class_init (CallyCloneClass *klass)
|
||||
{
|
||||
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
class->initialize = cally_clone_real_initialize;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_clone_init (CallyClone *clone)
|
||||
{
|
||||
/* nothing to do yet */
|
||||
}
|
||||
|
||||
/**
|
||||
* cally_clone_new:
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Creates a new #CallyClone for the given @actor. @actor must be a
|
||||
* [class@Clutter.Clone].
|
||||
*
|
||||
* Return value: the newly created #AtkObject
|
||||
*/
|
||||
AtkObject*
|
||||
cally_clone_new (ClutterActor *actor)
|
||||
{
|
||||
GObject *object = NULL;
|
||||
AtkObject *accessible = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_CLONE (actor), NULL);
|
||||
|
||||
object = g_object_new (CALLY_TYPE_CLONE, NULL);
|
||||
|
||||
accessible = ATK_OBJECT (object);
|
||||
atk_object_initialize (accessible, actor);
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_clone_real_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
ATK_OBJECT_CLASS (cally_clone_parent_class)->initialize (obj, data);
|
||||
|
||||
obj->role = ATK_ROLE_IMAGE;
|
||||
}
|
53
mutter/clutter/clutter/cally/cally-clone.h
Normal file
53
mutter/clutter/clutter/cally/cally-clone.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2010 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "cally/cally-actor.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_CLONE (cally_clone_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (CallyClone,
|
||||
cally_clone,
|
||||
CALLY,
|
||||
CLONE,
|
||||
CallyActor)
|
||||
|
||||
typedef struct _CallyClone CallyClone;
|
||||
typedef struct _CallyCloneClass CallyCloneClass;
|
||||
|
||||
struct _CallyCloneClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActorClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
AtkObject *cally_clone_new (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
108
mutter/clutter/clutter/cally/cally-factory.h
Normal file
108
mutter/clutter/clutter/cally/cally-factory.h
Normal file
@ -0,0 +1,108 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Based on gailfactory.h from GAIL
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <atk/atkobject.h>
|
||||
|
||||
/**
|
||||
* CALLY_ACCESSIBLE_FACTORY:
|
||||
* @type: GType of the accessible which is created by the factory
|
||||
* @type_as_function: prefix of the accessible object methods
|
||||
* @opt_create_accessible: method to instantiate the accessibility object
|
||||
*
|
||||
* Defines a new #AtkObjectFactory factory to create accessible
|
||||
* objects of a specific GType. It defines the factory GType and also
|
||||
* overrides the proper #AtkObjectFactory methods.
|
||||
*
|
||||
* It assumes that the accessibility object provides a
|
||||
* @opt_create_accessible method in order to create the accessibility
|
||||
* object. It returns a @type GType object.
|
||||
*/
|
||||
#define CALLY_ACCESSIBLE_FACTORY(type, type_as_function, opt_create_accessible) \
|
||||
\
|
||||
static GType \
|
||||
type_as_function ## _factory_get_accessible_type (void) \
|
||||
{ \
|
||||
return type; \
|
||||
} \
|
||||
\
|
||||
static AtkObject* \
|
||||
type_as_function ## _factory_create_accessible (GObject *obj) \
|
||||
{ \
|
||||
ClutterActor *actor; \
|
||||
AtkObject *accessible; \
|
||||
\
|
||||
g_return_val_if_fail (CLUTTER_ACTOR (obj), NULL); \
|
||||
\
|
||||
actor = CLUTTER_ACTOR (obj); \
|
||||
\
|
||||
accessible = opt_create_accessible (actor); \
|
||||
\
|
||||
return accessible; \
|
||||
} \
|
||||
\
|
||||
static void \
|
||||
type_as_function ## _factory_class_init (AtkObjectFactoryClass *klass) \
|
||||
{ \
|
||||
klass->create_accessible = type_as_function ## _factory_create_accessible; \
|
||||
klass->get_accessible_type = type_as_function ## _factory_get_accessible_type;\
|
||||
} \
|
||||
\
|
||||
static GType \
|
||||
type_as_function ## _factory_get_type (void) \
|
||||
{ \
|
||||
static GType t = 0; \
|
||||
\
|
||||
if (!t) \
|
||||
{ \
|
||||
char *name; \
|
||||
static const GTypeInfo tinfo = \
|
||||
{ \
|
||||
sizeof (AtkObjectFactoryClass), \
|
||||
NULL, NULL, (GClassInitFunc) type_as_function ## _factory_class_init, \
|
||||
NULL, NULL, sizeof (AtkObjectFactory), 0, NULL, NULL \
|
||||
}; \
|
||||
\
|
||||
name = g_strconcat (g_type_name (type), "Factory", NULL); \
|
||||
t = g_type_register_static ( \
|
||||
ATK_TYPE_OBJECT_FACTORY, name, &tinfo, 0); \
|
||||
g_free (name); \
|
||||
} \
|
||||
\
|
||||
return t; \
|
||||
}
|
||||
|
||||
/**
|
||||
* CALLY_ACTOR_SET_FACTORY:
|
||||
* @widget_type: GType of the clutter actor
|
||||
* @type_as_function: prefix of the accessible object methods
|
||||
*
|
||||
* Sets the #AtkObjectFactory to be used in order to instantiate
|
||||
* accessibility objects for the actor which GType is @widget_type.
|
||||
*/
|
||||
#define CALLY_ACTOR_SET_FACTORY(widget_type, type_as_function) \
|
||||
atk_registry_set_factory_type (atk_get_default_registry (), \
|
||||
widget_type, \
|
||||
type_as_function ## _factory_get_type ())
|
41
mutter/clutter/clutter/cally/cally-main.h
Normal file
41
mutter/clutter/clutter/cally/cally-main.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Some parts are based on GailWidget from GAIL
|
||||
* GAIL - The GNOME Accessibility Implementation Library
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <atk/atk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean cally_get_cally_initialized (void);
|
||||
CLUTTER_EXPORT
|
||||
gboolean cally_accessibility_init (void);
|
||||
|
||||
G_END_DECLS
|
294
mutter/clutter/clutter/cally/cally-root.c
Normal file
294
mutter/clutter/clutter/cally/cally-root.c
Normal file
@ -0,0 +1,294 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CallyRoot:
|
||||
*
|
||||
* Root object for the Cally toolkit
|
||||
*
|
||||
* #CallyRoot is the root object of the accessibility tree-like
|
||||
* hierarchy, exposing the application level.
|
||||
*
|
||||
* Somewhat equivalent to #GailTopLevel. We consider that this class
|
||||
* expose the a11y information of the [class@Clutter.StageManager], as the
|
||||
* children of this object are the different [class@Clutter.Stage] managed (so
|
||||
* the [class@GObject.Object] used in the [method@Atk.Object.initialize] is the
|
||||
* [class@Clutter.StageManager]).
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "cally/cally-root.h"
|
||||
|
||||
#include "clutter/clutter-actor.h"
|
||||
#include "clutter/clutter-stage-private.h"
|
||||
#include "clutter/clutter-stage-manager.h"
|
||||
|
||||
|
||||
/* GObject */
|
||||
static void cally_root_finalize (GObject *object);
|
||||
|
||||
/* AtkObject.h */
|
||||
static void cally_root_initialize (AtkObject *accessible,
|
||||
gpointer data);
|
||||
static gint cally_root_get_n_children (AtkObject *obj);
|
||||
static AtkObject * cally_root_ref_child (AtkObject *obj,
|
||||
gint i);
|
||||
static AtkObject * cally_root_get_parent (AtkObject *obj);
|
||||
static const char * cally_root_get_name (AtkObject *obj);
|
||||
|
||||
/* Private */
|
||||
static void cally_util_stage_added_cb (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage,
|
||||
gpointer data);
|
||||
static void cally_util_stage_removed_cb (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage,
|
||||
gpointer data);
|
||||
|
||||
typedef struct _CallyRootPrivate
|
||||
{
|
||||
/* We save the CallyStage objects. Other option could save the stage
|
||||
* list, and then just get the a11y object on the ref_child, etc. But
|
||||
* the ref_child is more common that the init and the stage-add,
|
||||
* stage-remove, so we avoid getting the accessible object
|
||||
* constantly
|
||||
*/
|
||||
GSList *stage_list;
|
||||
|
||||
/* signals id */
|
||||
gulong stage_added_id;
|
||||
gulong stage_removed_id;
|
||||
} CallyRootPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
|
||||
|
||||
static void
|
||||
cally_root_class_init (CallyRootClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = cally_root_finalize;
|
||||
|
||||
/* AtkObject */
|
||||
class->get_n_children = cally_root_get_n_children;
|
||||
class->ref_child = cally_root_ref_child;
|
||||
class->get_parent = cally_root_get_parent;
|
||||
class->initialize = cally_root_initialize;
|
||||
class->get_name = cally_root_get_name;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_root_init (CallyRoot *root)
|
||||
{
|
||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
||||
|
||||
priv->stage_list = NULL;
|
||||
priv->stage_added_id = 0;
|
||||
priv->stage_removed_id = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* cally_root_new:
|
||||
*
|
||||
* Creates a new #CallyRoot object.
|
||||
*
|
||||
* Return value: the newly created #AtkObject
|
||||
*/
|
||||
AtkObject*
|
||||
cally_root_new (void)
|
||||
{
|
||||
GObject *object = NULL;
|
||||
AtkObject *accessible = NULL;
|
||||
ClutterStageManager *stage_manager = NULL;
|
||||
|
||||
object = g_object_new (CALLY_TYPE_ROOT, NULL);
|
||||
|
||||
accessible = ATK_OBJECT (object);
|
||||
stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
atk_object_initialize (accessible, stage_manager);
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_root_finalize (GObject *object)
|
||||
{
|
||||
CallyRoot *root = CALLY_ROOT (object);
|
||||
GObject *stage_manager = NULL;
|
||||
CallyRootPrivate *priv;
|
||||
|
||||
g_return_if_fail (CALLY_IS_ROOT (object));
|
||||
|
||||
priv = cally_root_get_instance_private (root);
|
||||
if (priv->stage_list)
|
||||
{
|
||||
g_slist_free (priv->stage_list);
|
||||
priv->stage_list = NULL;
|
||||
}
|
||||
|
||||
stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
|
||||
|
||||
g_clear_signal_handler (&priv->stage_added_id, stage_manager);
|
||||
|
||||
g_clear_signal_handler (&priv->stage_removed_id, stage_manager);
|
||||
|
||||
G_OBJECT_CLASS (cally_root_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/* AtkObject.h */
|
||||
static void
|
||||
cally_root_initialize (AtkObject *accessible,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterStageManager *stage_manager = NULL;
|
||||
const GSList *iter = NULL;
|
||||
const GSList *stage_list = NULL;
|
||||
ClutterStage *clutter_stage = NULL;
|
||||
AtkObject *cally_stage = NULL;
|
||||
CallyRoot *root = CALLY_ROOT (accessible);
|
||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
||||
|
||||
|
||||
accessible->role = ATK_ROLE_APPLICATION;
|
||||
accessible->accessible_parent = NULL;
|
||||
|
||||
/* children initialization */
|
||||
stage_manager = CLUTTER_STAGE_MANAGER (data);
|
||||
stage_list = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
for (iter = stage_list; iter != NULL; iter = g_slist_next (iter))
|
||||
{
|
||||
clutter_stage = CLUTTER_STAGE (iter->data);
|
||||
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (clutter_stage));
|
||||
|
||||
atk_object_set_parent (cally_stage, ATK_OBJECT (root));
|
||||
|
||||
priv->stage_list = g_slist_append (priv->stage_list, cally_stage);
|
||||
}
|
||||
|
||||
priv->stage_added_id =
|
||||
g_signal_connect (G_OBJECT (stage_manager), "stage-added",
|
||||
G_CALLBACK (cally_util_stage_added_cb), root);
|
||||
|
||||
priv->stage_removed_id =
|
||||
g_signal_connect (G_OBJECT (stage_manager), "stage-removed",
|
||||
G_CALLBACK (cally_util_stage_removed_cb), root);
|
||||
|
||||
ATK_OBJECT_CLASS (cally_root_parent_class)->initialize (accessible, data);
|
||||
}
|
||||
|
||||
|
||||
static gint
|
||||
cally_root_get_n_children (AtkObject *obj)
|
||||
{
|
||||
CallyRoot *root = CALLY_ROOT (obj);
|
||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
||||
|
||||
return g_slist_length (priv->stage_list);
|
||||
}
|
||||
|
||||
static AtkObject*
|
||||
cally_root_ref_child (AtkObject *obj,
|
||||
gint i)
|
||||
{
|
||||
CallyRoot *cally_root = CALLY_ROOT (obj);
|
||||
CallyRootPrivate *priv = cally_root_get_instance_private (cally_root);
|
||||
GSList *stage_list = NULL;
|
||||
gint num = 0;
|
||||
AtkObject *item = NULL;
|
||||
|
||||
stage_list = priv->stage_list;
|
||||
num = g_slist_length (stage_list);
|
||||
|
||||
g_return_val_if_fail ((i < num)&&(i >= 0), NULL);
|
||||
|
||||
item = g_slist_nth_data (stage_list, i);
|
||||
if (!item)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_object_ref (item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
static AtkObject*
|
||||
cally_root_get_parent (AtkObject *obj)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
cally_root_get_name (AtkObject *obj)
|
||||
{
|
||||
return g_get_prgname ();
|
||||
}
|
||||
|
||||
/* -------------------------------- PRIVATE --------------------------------- */
|
||||
|
||||
static void
|
||||
cally_util_stage_added_cb (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
CallyRoot *root = CALLY_ROOT (data);
|
||||
AtkObject *cally_stage = NULL;
|
||||
CallyRootPrivate *priv = cally_root_get_instance_private (root);
|
||||
|
||||
gint index = -1;
|
||||
|
||||
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
atk_object_set_parent (cally_stage, ATK_OBJECT (root));
|
||||
|
||||
priv->stage_list = g_slist_append (priv->stage_list, cally_stage);
|
||||
|
||||
index = g_slist_index (priv->stage_list, cally_stage);
|
||||
g_signal_emit_by_name (root, "children_changed::add",
|
||||
index, cally_stage, NULL);
|
||||
g_signal_emit_by_name (cally_stage, "create", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cally_util_stage_removed_cb (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
CallyRoot *root = CALLY_ROOT (data);
|
||||
AtkObject *cally_stage = NULL;
|
||||
CallyRootPrivate *priv
|
||||
= cally_root_get_instance_private (root);
|
||||
gint index = -1;
|
||||
|
||||
cally_stage = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
index = g_slist_index (priv->stage_list, cally_stage);
|
||||
|
||||
priv->stage_list = g_slist_remove (priv->stage_list,
|
||||
cally_stage);
|
||||
|
||||
index = g_slist_index (priv->stage_list, cally_stage);
|
||||
g_signal_emit_by_name (root, "children_changed::remove",
|
||||
index, cally_stage, NULL);
|
||||
g_signal_emit_by_name (cally_stage, "destroy", 0);
|
||||
}
|
54
mutter/clutter/clutter/cally/cally-root.h
Normal file
54
mutter/clutter/clutter/cally/cally-root.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <atk/atk.h>
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_ROOT (cally_root_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (CallyRoot,
|
||||
cally_root,
|
||||
CALLY,
|
||||
ROOT,
|
||||
AtkGObjectAccessible)
|
||||
|
||||
typedef struct _CallyRoot CallyRoot;
|
||||
typedef struct _CallyRootClass CallyRootClass;
|
||||
|
||||
struct _CallyRootClass
|
||||
{
|
||||
/*< private >*/
|
||||
AtkGObjectAccessibleClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
AtkObject *cally_root_new (void);
|
||||
|
||||
G_END_DECLS
|
266
mutter/clutter/clutter/cally/cally-stage.c
Normal file
266
mutter/clutter/clutter/cally/cally-stage.c
Normal file
@ -0,0 +1,266 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CallyStage:
|
||||
*
|
||||
* Implementation of the ATK interfaces for a #ClutterStage
|
||||
*
|
||||
* #CallyStage implements the required ATK interfaces for [class@Clutter.Stage]
|
||||
*
|
||||
* Some implementation details: at this moment #CallyStage is used as
|
||||
* the most similar Window object in this toolkit (ie: emitting window
|
||||
* related signals), although the real purpose of [class@Clutter.Stage] is
|
||||
* being a canvas. Anyway, this is required for applications using
|
||||
* just clutter, or directly [class@Clutter.Stage]
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "cally/cally-stage.h"
|
||||
#include "cally/cally-actor-private.h"
|
||||
|
||||
/* AtkObject.h */
|
||||
static void cally_stage_real_initialize (AtkObject *obj,
|
||||
gpointer data);
|
||||
static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj);
|
||||
|
||||
/* AtkWindow */
|
||||
static void cally_stage_window_interface_init (AtkWindowIface *iface);
|
||||
|
||||
/* Auxiliary */
|
||||
static void cally_stage_activate_cb (ClutterStage *stage,
|
||||
gpointer data);
|
||||
static void cally_stage_deactivate_cb (ClutterStage *stage,
|
||||
gpointer data);
|
||||
|
||||
typedef struct _CallyStagePrivate
|
||||
{
|
||||
/* NULL means that the stage will receive the focus */
|
||||
ClutterActor *key_focus;
|
||||
|
||||
gboolean active;
|
||||
} CallyStagePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (CallyStage,
|
||||
cally_stage,
|
||||
CALLY_TYPE_ACTOR,
|
||||
G_ADD_PRIVATE (CallyStage)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
|
||||
cally_stage_window_interface_init));
|
||||
|
||||
static void
|
||||
cally_stage_class_init (CallyStageClass *klass)
|
||||
{
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
/* AtkObject */
|
||||
class->initialize = cally_stage_real_initialize;
|
||||
class->ref_state_set = cally_stage_ref_state_set;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_stage_init (CallyStage *cally_stage)
|
||||
{
|
||||
CallyStagePrivate *priv = cally_stage_get_instance_private (cally_stage);
|
||||
|
||||
priv->active = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* cally_stage_new:
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Creates a new #CallyStage for the given @actor. @actor should be a
|
||||
* [class@Clutter.Stage].
|
||||
*
|
||||
* Return value: the newly created #AtkObject
|
||||
*/
|
||||
AtkObject*
|
||||
cally_stage_new (ClutterActor *actor)
|
||||
{
|
||||
GObject *object = NULL;
|
||||
AtkObject *accessible = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (actor), NULL);
|
||||
|
||||
object = g_object_new (CALLY_TYPE_STAGE, NULL);
|
||||
|
||||
accessible = ATK_OBJECT (object);
|
||||
atk_object_initialize (accessible, actor);
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_stage_notify_key_focus_cb (ClutterStage *stage,
|
||||
GParamSpec *pspec,
|
||||
CallyStage *self)
|
||||
{
|
||||
ClutterActor *key_focus = NULL;
|
||||
AtkObject *new = NULL;
|
||||
CallyStagePrivate *priv = cally_stage_get_instance_private (self);
|
||||
|
||||
if (priv->active == FALSE)
|
||||
return;
|
||||
|
||||
key_focus = clutter_stage_get_key_focus (stage);
|
||||
|
||||
if (key_focus != priv->key_focus)
|
||||
{
|
||||
AtkObject *old = NULL;
|
||||
|
||||
if (priv->key_focus != NULL)
|
||||
{
|
||||
if (priv->key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->key_focus),
|
||||
(gpointer *) &priv->key_focus);
|
||||
}
|
||||
old = clutter_actor_get_accessible (priv->key_focus);
|
||||
}
|
||||
else
|
||||
old = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
atk_object_notify_state_change (old,
|
||||
ATK_STATE_FOCUSED,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
/* we keep notifying the focus gain without checking previous
|
||||
* key-focus to avoid some missing events due timing
|
||||
*/
|
||||
priv->key_focus = key_focus;
|
||||
|
||||
if (key_focus != NULL)
|
||||
{
|
||||
/* ensure that if the key focus goes away, the field inside
|
||||
* CallyStage is reset. see bug:
|
||||
*
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=692706
|
||||
*
|
||||
* we remove the weak pointer above.
|
||||
*/
|
||||
if (key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (priv->key_focus),
|
||||
(gpointer *) &priv->key_focus);
|
||||
}
|
||||
|
||||
new = clutter_actor_get_accessible (key_focus);
|
||||
}
|
||||
else
|
||||
new = clutter_actor_get_accessible (CLUTTER_ACTOR (stage));
|
||||
|
||||
atk_object_notify_state_change (new,
|
||||
ATK_STATE_FOCUSED,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
cally_stage_real_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterStage *stage = NULL;
|
||||
|
||||
g_return_if_fail (CALLY_IS_STAGE (obj));
|
||||
|
||||
ATK_OBJECT_CLASS (cally_stage_parent_class)->initialize (obj, data);
|
||||
|
||||
stage = CLUTTER_STAGE (CALLY_GET_CLUTTER_ACTOR (obj));
|
||||
|
||||
g_signal_connect (stage, "activate", G_CALLBACK (cally_stage_activate_cb), obj);
|
||||
g_signal_connect (stage, "deactivate", G_CALLBACK (cally_stage_deactivate_cb), obj);
|
||||
g_signal_connect (stage, "notify::key-focus",
|
||||
G_CALLBACK (cally_stage_notify_key_focus_cb), obj);
|
||||
|
||||
atk_object_set_role (obj, ATK_ROLE_WINDOW);
|
||||
}
|
||||
|
||||
static AtkStateSet*
|
||||
cally_stage_ref_state_set (AtkObject *obj)
|
||||
{
|
||||
CallyStage *cally_stage = NULL;
|
||||
AtkStateSet *state_set = NULL;
|
||||
ClutterStage *stage = NULL;
|
||||
CallyStagePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CALLY_IS_STAGE (obj), NULL);
|
||||
cally_stage = CALLY_STAGE (obj);
|
||||
priv = cally_stage_get_instance_private (cally_stage);
|
||||
|
||||
state_set = ATK_OBJECT_CLASS (cally_stage_parent_class)->ref_state_set (obj);
|
||||
stage = CLUTTER_STAGE (CALLY_GET_CLUTTER_ACTOR (cally_stage));
|
||||
|
||||
if (stage == NULL)
|
||||
return state_set;
|
||||
|
||||
if (priv->active)
|
||||
atk_state_set_add_state (state_set, ATK_STATE_ACTIVE);
|
||||
|
||||
return state_set;
|
||||
}
|
||||
|
||||
/* AtkWindow */
|
||||
static void
|
||||
cally_stage_window_interface_init (AtkWindowIface *iface)
|
||||
{
|
||||
/* At this moment AtkWindow is just about signals */
|
||||
}
|
||||
|
||||
/* Auxiliary */
|
||||
static void
|
||||
cally_stage_activate_cb (ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
CallyStage *cally_stage = NULL;
|
||||
CallyStagePrivate *priv;
|
||||
|
||||
g_return_if_fail (CALLY_IS_STAGE (data));
|
||||
|
||||
cally_stage = CALLY_STAGE (data);
|
||||
priv = cally_stage_get_instance_private (cally_stage);
|
||||
|
||||
priv->active = TRUE;
|
||||
|
||||
atk_object_notify_state_change (ATK_OBJECT (cally_stage),
|
||||
ATK_STATE_ACTIVE, TRUE);
|
||||
|
||||
g_signal_emit_by_name (cally_stage, "activate", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cally_stage_deactivate_cb (ClutterStage *stage,
|
||||
gpointer data)
|
||||
{
|
||||
CallyStage *cally_stage = NULL;
|
||||
CallyStagePrivate *priv;
|
||||
|
||||
g_return_if_fail (CALLY_IS_STAGE (data));
|
||||
|
||||
cally_stage = CALLY_STAGE (data);
|
||||
priv = cally_stage_get_instance_private (cally_stage);
|
||||
|
||||
priv->active = FALSE;
|
||||
|
||||
atk_object_notify_state_change (ATK_OBJECT (cally_stage),
|
||||
ATK_STATE_ACTIVE, FALSE);
|
||||
|
||||
g_signal_emit_by_name (cally_stage, "deactivate", 0);
|
||||
}
|
53
mutter/clutter/clutter/cally/cally-stage.h
Normal file
53
mutter/clutter/clutter/cally/cally-stage.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "cally/cally-actor.h"
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_STAGE (cally_stage_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (CallyStage,
|
||||
cally_stage,
|
||||
CALLY,
|
||||
STAGE,
|
||||
CallyActor)
|
||||
|
||||
typedef struct _CallyStage CallyStage;
|
||||
typedef struct _CallyStageClass CallyStageClass;
|
||||
|
||||
struct _CallyStageClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActorClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
AtkObject *cally_stage_new (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
2329
mutter/clutter/clutter/cally/cally-text.c
Normal file
2329
mutter/clutter/clutter/cally/cally-text.c
Normal file
File diff suppressed because it is too large
Load Diff
53
mutter/clutter/clutter/cally/cally-text.h
Normal file
53
mutter/clutter/clutter/cally/cally-text.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "cally/cally-actor.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_TEXT (cally_text_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (CallyText,
|
||||
cally_text,
|
||||
CALLY,
|
||||
TEXT,
|
||||
CallyActor)
|
||||
|
||||
typedef struct _CallyText CallyText;
|
||||
typedef struct _CallyTextClass CallyTextClass;
|
||||
|
||||
struct _CallyTextClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActorClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
AtkObject* cally_text_new (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
351
mutter/clutter/clutter/cally/cally-util.c
Normal file
351
mutter/clutter/clutter/cally/cally-util.c
Normal file
@ -0,0 +1,351 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Based on GailUtil from GAIL
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CallyUtil:
|
||||
*
|
||||
* #AtkUtil implementation
|
||||
*
|
||||
* #CallyUtil implements #AtkUtil abstract methods. Although it
|
||||
* includes the name "Util" it is in fact one of the most important
|
||||
* interfaces to be implemented in any ATK toolkit implementation.
|
||||
|
||||
* For instance, it defines [func@Atk.get_root], the method that returns
|
||||
* the root object in the hierarchy. Without it, you don't have
|
||||
* available any accessible object.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cally/cally-util.h"
|
||||
#include "cally/cally-root.h"
|
||||
#include "cally/cally-stage.h"
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
#define DEFAULT_PASSWORD_CHAR '*'
|
||||
|
||||
/* atkutil.h */
|
||||
|
||||
static guint cally_util_add_key_event_listener (AtkKeySnoopFunc listener,
|
||||
gpointer data);
|
||||
static void cally_util_remove_key_event_listener (guint remove_listener);
|
||||
static AtkObject* cally_util_get_root (void);
|
||||
static const gchar * cally_util_get_toolkit_name (void);
|
||||
static const gchar * cally_util_get_toolkit_version (void);
|
||||
|
||||
/* private */
|
||||
static gboolean notify_hf (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data);
|
||||
static void insert_hf (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data);
|
||||
|
||||
/* This is just a copy of the Gail one, a shared library or place to
|
||||
define it could be a good idea. */
|
||||
typedef struct _CallyKeyEventInfo CallyKeyEventInfo;
|
||||
|
||||
struct _CallyKeyEventInfo
|
||||
{
|
||||
AtkKeySnoopFunc listener;
|
||||
gpointer func_data;
|
||||
};
|
||||
|
||||
static AtkObject* root = NULL;
|
||||
static GHashTable *key_listener_list = NULL;
|
||||
|
||||
|
||||
G_DEFINE_TYPE (CallyUtil, cally_util, ATK_TYPE_UTIL);
|
||||
|
||||
static void
|
||||
cally_util_class_init (CallyUtilClass *klass)
|
||||
{
|
||||
AtkUtilClass *atk_class;
|
||||
gpointer data;
|
||||
|
||||
data = g_type_class_peek (ATK_TYPE_UTIL);
|
||||
atk_class = ATK_UTIL_CLASS (data);
|
||||
|
||||
atk_class->add_key_event_listener = cally_util_add_key_event_listener;
|
||||
atk_class->remove_key_event_listener = cally_util_remove_key_event_listener;
|
||||
atk_class->get_root = cally_util_get_root;
|
||||
atk_class->get_toolkit_name = cally_util_get_toolkit_name;
|
||||
atk_class->get_toolkit_version = cally_util_get_toolkit_version;
|
||||
|
||||
/* FIXME: Instead of create this on the class, I think that would
|
||||
worth to implement CallyUtil as a singleton instance, so the
|
||||
class methods will access this instance. This will be a good
|
||||
future enhancement, meanwhile, just using the same *working*
|
||||
implementation used on GailUtil */
|
||||
}
|
||||
|
||||
static void
|
||||
cally_util_init (CallyUtil *cally_util)
|
||||
{
|
||||
/* instance init: usually not required */
|
||||
}
|
||||
|
||||
/* ------------------------------ ATK UTIL METHODS -------------------------- */
|
||||
|
||||
static AtkObject*
|
||||
cally_util_get_root (void)
|
||||
{
|
||||
if (!root)
|
||||
root = cally_root_new ();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
cally_util_get_toolkit_name (void)
|
||||
{
|
||||
return "clutter";
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
cally_util_get_toolkit_version (void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
static guint
|
||||
cally_util_add_key_event_listener (AtkKeySnoopFunc listener,
|
||||
gpointer data)
|
||||
{
|
||||
static guint key = 1;
|
||||
CallyKeyEventInfo *event_info = NULL;
|
||||
|
||||
if (!key_listener_list)
|
||||
key_listener_list = g_hash_table_new_full (NULL, NULL, NULL, g_free);
|
||||
|
||||
event_info = g_new (CallyKeyEventInfo, 1);
|
||||
event_info->listener = listener;
|
||||
event_info->func_data = data;
|
||||
|
||||
g_hash_table_insert (key_listener_list, GUINT_TO_POINTER (key++), event_info);
|
||||
/* XXX: we don't check to see if n_listeners > MAXUINT */
|
||||
return key - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_util_remove_key_event_listener (guint remove_listener)
|
||||
{
|
||||
if (!g_hash_table_remove (key_listener_list, GUINT_TO_POINTER (remove_listener))) {
|
||||
g_warning ("Not able to remove listener with id %i", remove_listener);
|
||||
}
|
||||
|
||||
if (g_hash_table_size (key_listener_list) == 0)
|
||||
{
|
||||
g_hash_table_destroy (key_listener_list);
|
||||
key_listener_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------ PRIVATE FUNCTIONS ------------------------- */
|
||||
|
||||
static AtkKeyEventStruct *
|
||||
atk_key_event_from_clutter_event_key (ClutterKeyEvent *clutter_event,
|
||||
gunichar password_char)
|
||||
{
|
||||
AtkKeyEventStruct *atk_event = g_new0 (AtkKeyEventStruct, 1);
|
||||
gunichar key_unichar;
|
||||
|
||||
switch (clutter_event_type ((ClutterEvent *) clutter_event))
|
||||
{
|
||||
case CLUTTER_KEY_PRESS:
|
||||
atk_event->type = ATK_KEY_EVENT_PRESS;
|
||||
break;
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
atk_event->type = ATK_KEY_EVENT_RELEASE;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (password_char)
|
||||
atk_event->state = 0;
|
||||
else
|
||||
atk_event->state = clutter_event_get_state ((ClutterEvent *) clutter_event);
|
||||
|
||||
/* We emit the clutter keyval. This is not exactly the one expected
|
||||
by AtkKeyEventStruct, as it expects a Gdk-like event, with the
|
||||
modifiers applied. But to avoid a dependency to gdk, we delegate
|
||||
that on the AT application.
|
||||
More information: Bug 1952 and bug 2072
|
||||
*/
|
||||
if (password_char)
|
||||
atk_event->keyval = clutter_unicode_to_keysym (password_char);
|
||||
else
|
||||
atk_event->keyval = clutter_event_get_key_symbol ((ClutterEvent *) clutter_event);
|
||||
|
||||
/* It is expected to store a key defining string here (ie "Space" in
|
||||
case you press a space). Anyway, there are no function on clutter
|
||||
to obtain that, and we want to avoid a gdk dependency here, so we
|
||||
delegate on the AT application to obtain that string using the
|
||||
rest of the data on the ATK event struct.
|
||||
|
||||
More information: Bug 1952 and 2072
|
||||
*/
|
||||
|
||||
if (password_char)
|
||||
key_unichar = password_char;
|
||||
else
|
||||
key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) clutter_event);
|
||||
|
||||
if (g_unichar_validate (key_unichar) && !g_unichar_iscntrl (key_unichar))
|
||||
{
|
||||
GString *new = NULL;
|
||||
|
||||
new = g_string_new ("");
|
||||
new = g_string_insert_unichar (new, 0, key_unichar);
|
||||
atk_event->string = g_string_free (new, FALSE);
|
||||
}
|
||||
else
|
||||
atk_event->string = NULL;
|
||||
|
||||
atk_event->length = 0;
|
||||
|
||||
/* Computing the hardware keycode from the password-char is
|
||||
difficult. But we are in a password situation. We are already a
|
||||
unichar that it is not the original one. Providing a "almost
|
||||
real" keycode is irrelevant */
|
||||
if (password_char)
|
||||
atk_event->keycode = 0;
|
||||
else
|
||||
atk_event->keycode = clutter_event_get_key_code ((ClutterEvent *) clutter_event);
|
||||
|
||||
atk_event->timestamp = clutter_event_get_time ((ClutterEvent *) clutter_event);
|
||||
|
||||
#ifdef CALLY_DEBUG
|
||||
|
||||
g_debug ("CallyKeyEvent:\tsym 0x%x\n\t\tmods %x\n\t\tcode %u\n\t\ttime %lx \n\t\tstring %s\n",
|
||||
(unsigned int) atk_event->keyval,
|
||||
(unsigned int) atk_event->state,
|
||||
(unsigned int) atk_event->keycode,
|
||||
(unsigned long int) atk_event->timestamp,
|
||||
atk_event->string);
|
||||
#endif
|
||||
|
||||
return atk_event;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
notify_hf (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
CallyKeyEventInfo *info = (CallyKeyEventInfo *) value;
|
||||
AtkKeyEventStruct *key_event = (AtkKeyEventStruct *)data;
|
||||
|
||||
return (*(AtkKeySnoopFunc) info->listener) (key_event, info->func_data) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
insert_hf (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
GHashTable *new_table = (GHashTable *) data;
|
||||
g_hash_table_insert (new_table, key, value);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 0 if the key of that event is visible, in other case the password
|
||||
* char
|
||||
*/
|
||||
static gunichar
|
||||
check_key_visibility (ClutterStage *stage)
|
||||
{
|
||||
AtkObject *accessible;
|
||||
ClutterActor *focus;
|
||||
|
||||
focus = clutter_stage_get_key_focus (stage);
|
||||
accessible = clutter_actor_get_accessible (focus);
|
||||
|
||||
g_return_val_if_fail (accessible != NULL, 0);
|
||||
|
||||
if (atk_object_get_role (accessible) != ATK_ROLE_PASSWORD_TEXT)
|
||||
return 0;
|
||||
|
||||
/* If it is a clutter text, we use his password char. Note that
|
||||
although at Clutter toolkit itself, only ClutterText exposes a
|
||||
password role, nothing prevents on any derived toolkit (like st)
|
||||
to create a new actor that can behave like a password entry. And
|
||||
the key event will still be emitted here. Although in that case
|
||||
we would lose any password char from the derived toolkit, it is
|
||||
still better fill this with a default unichar that the original
|
||||
one */
|
||||
|
||||
if (CLUTTER_IS_TEXT (focus))
|
||||
return clutter_text_get_password_char (CLUTTER_TEXT (focus));
|
||||
else
|
||||
return DEFAULT_PASSWORD_CHAR;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cally_snoop_key_event (ClutterStage *stage,
|
||||
ClutterKeyEvent *key)
|
||||
{
|
||||
ClutterEvent *event = (ClutterEvent *) key;
|
||||
AtkKeyEventStruct *key_event = NULL;
|
||||
ClutterEventType event_type;
|
||||
gboolean consumed = FALSE;
|
||||
gunichar password_char = 0;
|
||||
|
||||
event_type = clutter_event_type (event);
|
||||
|
||||
/* filter key events */
|
||||
if ((event_type != CLUTTER_KEY_PRESS) && (event_type != CLUTTER_KEY_RELEASE))
|
||||
return FALSE;
|
||||
|
||||
if (key_listener_list)
|
||||
{
|
||||
GHashTable *new_hash = g_hash_table_new (NULL, NULL);
|
||||
|
||||
g_hash_table_foreach (key_listener_list, insert_hf, new_hash);
|
||||
password_char = check_key_visibility (stage);
|
||||
key_event = atk_key_event_from_clutter_event_key (key, password_char);
|
||||
/* func data is inside the hash table */
|
||||
consumed = g_hash_table_foreach_steal (new_hash, notify_hf, key_event) > 0;
|
||||
g_hash_table_destroy (new_hash);
|
||||
|
||||
g_free (key_event->string);
|
||||
g_free (key_event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void
|
||||
_cally_util_override_atk_util (void)
|
||||
{
|
||||
AtkUtilClass *atk_class = ATK_UTIL_CLASS (g_type_class_ref (ATK_TYPE_UTIL));
|
||||
|
||||
atk_class->add_key_event_listener = cally_util_add_key_event_listener;
|
||||
atk_class->remove_key_event_listener = cally_util_remove_key_event_listener;
|
||||
atk_class->get_root = cally_util_get_root;
|
||||
atk_class->get_toolkit_name = cally_util_get_toolkit_name;
|
||||
atk_class->get_toolkit_version = cally_util_get_toolkit_version;
|
||||
}
|
55
mutter/clutter/clutter/cally/cally-util.h
Normal file
55
mutter/clutter/clutter/cally/cally-util.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include <atk/atk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_UTIL (cally_util_get_type ())
|
||||
|
||||
typedef struct _CallyUtil CallyUtil;
|
||||
typedef struct _CallyUtilClass CallyUtilClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (CallyUtil,
|
||||
cally_util,
|
||||
CALLY,
|
||||
UTIL,
|
||||
AtkUtil)
|
||||
|
||||
struct _CallyUtilClass
|
||||
{
|
||||
/*< private >*/
|
||||
AtkUtilClass parent_class;
|
||||
};
|
||||
|
||||
void _cally_util_override_atk_util (void);
|
||||
|
||||
gboolean cally_snoop_key_event (ClutterStage *stage,
|
||||
ClutterKeyEvent *key);
|
||||
|
||||
G_END_DECLS
|
79
mutter/clutter/clutter/cally/cally.c
Normal file
79
mutter/clutter/clutter/cally/cally.c
Normal file
@ -0,0 +1,79 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "cally/cally.h"
|
||||
|
||||
#include "cally/cally-actor.h"
|
||||
#include "cally/cally-stage.h"
|
||||
#include "cally/cally-text.h"
|
||||
#include "cally/cally-clone.h"
|
||||
|
||||
#include "cally/cally-factory.h"
|
||||
#include "cally/cally-util.h"
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
/* factories initialization*/
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_STAGE, cally_stage, cally_stage_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
|
||||
|
||||
/**
|
||||
* cally_accessibility_init:
|
||||
*
|
||||
* Initializes the accessibility support.
|
||||
*
|
||||
* Return value: %TRUE if accessibility support has been correctly
|
||||
* initialized.
|
||||
*/
|
||||
gboolean
|
||||
cally_accessibility_init (void)
|
||||
{
|
||||
/* setting the factories */
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_STAGE, cally_stage);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone);
|
||||
|
||||
/* Initialize the CallyUtility class */
|
||||
_cally_util_override_atk_util ();
|
||||
|
||||
CLUTTER_NOTE (MISC, "Clutter Accessibility initialized");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* cally_get_cally_initialized:
|
||||
*
|
||||
* Returns if the accessibility support using cally is enabled.
|
||||
*
|
||||
* Return value: %TRUE if accessibility support has been correctly
|
||||
* initialized.
|
||||
*/
|
||||
gboolean cally_get_cally_initialized (void)
|
||||
{
|
||||
return !g_strcmp0 (atk_get_toolkit_name (), "clutter");
|
||||
}
|
34
mutter/clutter/clutter/cally/cally.h
Normal file
34
mutter/clutter/clutter/cally/cally.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define __CALLY_H_INSIDE__
|
||||
|
||||
#include "cally/cally-actor.h"
|
||||
#include "cally/cally-clone.h"
|
||||
#include "cally/cally-factory.h"
|
||||
#include "cally/cally-main.h"
|
||||
#include "cally/cally-root.h"
|
||||
#include "cally/cally-stage.h"
|
||||
#include "cally/cally-text.h"
|
||||
#include "cally/cally-util.h"
|
||||
|
||||
#undef __CALLY_H_INSIDE__
|
53
mutter/clutter/clutter/clutter-action-private.h
Normal file
53
mutter/clutter/clutter/clutter-action-private.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2021 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-action.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void clutter_action_set_phase (ClutterAction *action,
|
||||
ClutterEventPhase phase);
|
||||
|
||||
gboolean clutter_action_handle_event (ClutterAction *action,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void clutter_action_sequence_cancelled (ClutterAction *action,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
gboolean clutter_action_register_sequence (ClutterAction *self,
|
||||
const ClutterEvent *event);
|
||||
|
||||
int clutter_action_setup_sequence_relationship (ClutterAction *action_1,
|
||||
ClutterAction *action_2,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
G_END_DECLS
|
146
mutter/clutter/clutter/clutter-action.c
Normal file
146
mutter/clutter/clutter/clutter-action.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterAction:
|
||||
*
|
||||
* Abstract class for event-related logic
|
||||
*
|
||||
* #ClutterAction is an abstract base class for event-related actions that
|
||||
* modify the user interaction of a [class@Actor], just like
|
||||
* [class@Constraint] is an abstract class for modifiers of an actor's
|
||||
* position or size.
|
||||
*
|
||||
* Implementations of #ClutterAction are associated to an actor and can
|
||||
* provide behavioral changes when dealing with user input - for instance
|
||||
* drag and drop capabilities, or scrolling, or panning - by using the
|
||||
* various event-related signals provided by [class@Actor] itself.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-action.h"
|
||||
#include "clutter/clutter-action-private.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
typedef struct _ClutterActionPrivate ClutterActionPrivate;
|
||||
|
||||
struct _ClutterActionPrivate
|
||||
{
|
||||
ClutterEventPhase phase;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterAction, clutter_action,
|
||||
CLUTTER_TYPE_ACTOR_META)
|
||||
|
||||
static gboolean
|
||||
clutter_action_handle_event_default (ClutterAction *action,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_action_class_init (ClutterActionClass *klass)
|
||||
{
|
||||
klass->handle_event = clutter_action_handle_event_default;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_action_init (ClutterAction *self)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
clutter_action_set_phase (ClutterAction *action,
|
||||
ClutterEventPhase phase)
|
||||
{
|
||||
ClutterActionPrivate *priv;
|
||||
|
||||
priv = clutter_action_get_instance_private (action);
|
||||
priv->phase = phase;
|
||||
}
|
||||
|
||||
ClutterEventPhase
|
||||
clutter_action_get_phase (ClutterAction *action)
|
||||
{
|
||||
ClutterActionPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTION (action), CLUTTER_PHASE_CAPTURE);
|
||||
|
||||
priv = clutter_action_get_instance_private (action);
|
||||
|
||||
return priv->phase;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_action_handle_event (ClutterAction *action,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
gboolean retval;
|
||||
|
||||
g_object_ref (action);
|
||||
retval = CLUTTER_ACTION_GET_CLASS (action)->handle_event (action, event);
|
||||
g_object_unref (action);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_action_sequence_cancelled (ClutterAction *action,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
ClutterActionClass *action_class = CLUTTER_ACTION_GET_CLASS (action);
|
||||
|
||||
if (action_class->sequence_cancelled)
|
||||
action_class->sequence_cancelled (action, device, sequence);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_action_register_sequence (ClutterAction *self,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterActionClass *action_class = CLUTTER_ACTION_GET_CLASS (self);
|
||||
|
||||
if (action_class->register_sequence)
|
||||
return action_class->register_sequence (self, event);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
clutter_action_setup_sequence_relationship (ClutterAction *action_1,
|
||||
ClutterAction *action_2,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
ClutterActionClass *action_class = CLUTTER_ACTION_GET_CLASS (action_1);
|
||||
|
||||
if (action_class->setup_sequence_relationship)
|
||||
return action_class->setup_sequence_relationship (action_1, action_2, device, sequence);
|
||||
|
||||
return 0;
|
||||
}
|
99
mutter/clutter/clutter/clutter-action.h
Normal file
99
mutter/clutter/clutter/clutter-action.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-actor-meta.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_ACTION (clutter_action_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterAction, clutter_action,
|
||||
CLUTTER, ACTION, ClutterActorMeta);
|
||||
|
||||
/**
|
||||
* ClutterActionClass:
|
||||
*
|
||||
* The ClutterActionClass structure contains only private data
|
||||
*/
|
||||
struct _ClutterActionClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorMetaClass parent_class;
|
||||
|
||||
gboolean (* handle_event) (ClutterAction *action,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void (* sequence_cancelled) (ClutterAction *action,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
gboolean (* register_sequence) (ClutterAction *self,
|
||||
const ClutterEvent *event);
|
||||
|
||||
int (* setup_sequence_relationship) (ClutterAction *action_1,
|
||||
ClutterAction *action_2,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
};
|
||||
|
||||
/* ClutterActor API */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_action (ClutterActor *self,
|
||||
ClutterAction *action);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_action_with_name (ClutterActor *self,
|
||||
const gchar *name,
|
||||
ClutterAction *action);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_action_full (ClutterActor *self,
|
||||
const char *name,
|
||||
ClutterEventPhase phase,
|
||||
ClutterAction *action);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_action (ClutterActor *self,
|
||||
ClutterAction *action);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_action_by_name (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
ClutterAction *clutter_actor_get_action (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_actor_get_actions (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_clear_actions (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_actions (ClutterActor *self);
|
||||
|
||||
ClutterEventPhase clutter_action_get_phase (ClutterAction *action);
|
||||
|
||||
G_END_DECLS
|
9
mutter/clutter/clutter/clutter-actor-box-private.h
Normal file
9
mutter/clutter/clutter/clutter-actor-box-private.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box);
|
||||
|
||||
G_END_DECLS
|
606
mutter/clutter/clutter/clutter-actor-box.c
Normal file
606
mutter/clutter/clutter/clutter-actor-box.c
Normal file
@ -0,0 +1,606 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
#include "clutter/clutter-interval.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-actor-box-private.h"
|
||||
|
||||
/**
|
||||
* clutter_actor_box_new:
|
||||
* @x_1: X coordinate of the top left point
|
||||
* @y_1: Y coordinate of the top left point
|
||||
* @x_2: X coordinate of the bottom right point
|
||||
* @y_2: Y coordinate of the bottom right point
|
||||
*
|
||||
* Allocates a new [struct@ActorBox] using the passed coordinates
|
||||
* for the top left and bottom right points.
|
||||
*
|
||||
* This function is the logical equivalent of:
|
||||
*
|
||||
* ```c
|
||||
* clutter_actor_box_init (clutter_actor_box_alloc (),
|
||||
* x_1, y_1,
|
||||
* x_2, y_2);
|
||||
* ```
|
||||
*
|
||||
* Return value: (transfer full): the newly allocated #ClutterActorBox.
|
||||
* Use [method@ActorBox.free] to free the resources
|
||||
*/
|
||||
ClutterActorBox *
|
||||
clutter_actor_box_new (gfloat x_1,
|
||||
gfloat y_1,
|
||||
gfloat x_2,
|
||||
gfloat y_2)
|
||||
{
|
||||
return clutter_actor_box_init (clutter_actor_box_alloc (),
|
||||
x_1, y_1,
|
||||
x_2, y_2);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_alloc:
|
||||
*
|
||||
* Allocates a new [struct@ActorBox].
|
||||
*
|
||||
* Return value: (transfer full): the newly allocated #ClutterActorBox.
|
||||
* Use [method@ActorBox.free] to free its resources
|
||||
*/
|
||||
ClutterActorBox *
|
||||
clutter_actor_box_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterActorBox, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_init:
|
||||
* @box: a #ClutterActorBox
|
||||
* @x_1: X coordinate of the top left point
|
||||
* @y_1: Y coordinate of the top left point
|
||||
* @x_2: X coordinate of the bottom right point
|
||||
* @y_2: Y coordinate of the bottom right point
|
||||
*
|
||||
* Initializes @box with the given coordinates.
|
||||
*
|
||||
* Return value: (transfer none): the initialized #ClutterActorBox
|
||||
*/
|
||||
ClutterActorBox *
|
||||
clutter_actor_box_init (ClutterActorBox *box,
|
||||
gfloat x_1,
|
||||
gfloat y_1,
|
||||
gfloat x_2,
|
||||
gfloat y_2)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, NULL);
|
||||
|
||||
box->x1 = x_1;
|
||||
box->y1 = y_1;
|
||||
box->x2 = x_2;
|
||||
box->y2 = y_2;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_init_rect:
|
||||
* @box: a #ClutterActorBox
|
||||
* @x: X coordinate of the origin
|
||||
* @y: Y coordinate of the origin
|
||||
* @width: width of the box
|
||||
* @height: height of the box
|
||||
*
|
||||
* Initializes @box with the given origin and size.
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_init_rect (ClutterActorBox *box,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat width,
|
||||
gfloat height)
|
||||
{
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
box->x1 = x;
|
||||
box->y1 = y;
|
||||
box->x2 = box->x1 + width;
|
||||
box->y2 = box->y1 + height;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_copy:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Copies @box
|
||||
*
|
||||
* Return value: a newly allocated copy of #ClutterActorBox. Use
|
||||
* [method@ActorBox.free] to free the allocated resources
|
||||
*/
|
||||
ClutterActorBox *
|
||||
clutter_actor_box_copy (const ClutterActorBox *box)
|
||||
{
|
||||
if (G_LIKELY (box != NULL))
|
||||
return g_memdup2 (box, sizeof (ClutterActorBox));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_free:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Frees a #ClutterActorBox allocated using [ctor@ActorBox.new]
|
||||
* or [method@ActorBox.copy].
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_free (ClutterActorBox *box)
|
||||
{
|
||||
if (G_LIKELY (box != NULL))
|
||||
g_free (box);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_equal:
|
||||
* @box_a: a #ClutterActorBox
|
||||
* @box_b: a #ClutterActorBox
|
||||
*
|
||||
* Checks @box_a and @box_b for equality
|
||||
*
|
||||
* Return value: %TRUE if the passed #ClutterActorBox are equal
|
||||
*/
|
||||
gboolean
|
||||
clutter_actor_box_equal (const ClutterActorBox *box_a,
|
||||
const ClutterActorBox *box_b)
|
||||
{
|
||||
g_return_val_if_fail (box_a != NULL && box_b != NULL, FALSE);
|
||||
|
||||
if (box_a == box_b)
|
||||
return TRUE;
|
||||
|
||||
return box_a->x1 == box_b->x1 && box_a->y1 == box_b->y1 &&
|
||||
box_a->x2 == box_b->x2 && box_a->y2 == box_b->y2;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_x:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Retrieves the X coordinate of the origin of @box
|
||||
*
|
||||
* Return value: the X coordinate of the origin
|
||||
*/
|
||||
gfloat
|
||||
clutter_actor_box_get_x (const ClutterActorBox *box)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, 0.);
|
||||
|
||||
return box->x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_y:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Retrieves the Y coordinate of the origin of @box
|
||||
*
|
||||
* Return value: the Y coordinate of the origin
|
||||
*/
|
||||
gfloat
|
||||
clutter_actor_box_get_y (const ClutterActorBox *box)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, 0.);
|
||||
|
||||
return box->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_width:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Retrieves the width of the @box
|
||||
*
|
||||
* Return value: the width of the box
|
||||
*/
|
||||
gfloat
|
||||
clutter_actor_box_get_width (const ClutterActorBox *box)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, 0.);
|
||||
|
||||
return box->x2 - box->x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_height:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Retrieves the height of the @box
|
||||
*
|
||||
* Return value: the height of the box
|
||||
*/
|
||||
gfloat
|
||||
clutter_actor_box_get_height (const ClutterActorBox *box)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, 0.);
|
||||
|
||||
return box->y2 - box->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_origin:
|
||||
* @box: a #ClutterActorBox
|
||||
* @x: (out) (allow-none): return location for the X coordinate, or %NULL
|
||||
* @y: (out) (allow-none): return location for the Y coordinate, or %NULL
|
||||
*
|
||||
* Retrieves the origin of @box
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_get_origin (const ClutterActorBox *box,
|
||||
gfloat *x,
|
||||
gfloat *y)
|
||||
{
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
if (x)
|
||||
*x = box->x1;
|
||||
|
||||
if (y)
|
||||
*y = box->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_size:
|
||||
* @box: a #ClutterActorBox
|
||||
* @width: (out) (allow-none): return location for the width, or %NULL
|
||||
* @height: (out) (allow-none): return location for the height, or %NULL
|
||||
*
|
||||
* Retrieves the size of @box
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_get_size (const ClutterActorBox *box,
|
||||
gfloat *width,
|
||||
gfloat *height)
|
||||
{
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
if (width)
|
||||
*width = box->x2 - box->x1;
|
||||
|
||||
if (height)
|
||||
*height = box->y2 - box->y1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_get_area:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Retrieves the area of @box
|
||||
*
|
||||
* Return value: the area of a #ClutterActorBox, in pixels
|
||||
*/
|
||||
gfloat
|
||||
clutter_actor_box_get_area (const ClutterActorBox *box)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, 0.);
|
||||
|
||||
return (box->x2 - box->x1) * (box->y2 - box->y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_contains:
|
||||
* @box: a #ClutterActorBox
|
||||
* @x: X coordinate of the point
|
||||
* @y: Y coordinate of the point
|
||||
*
|
||||
* Checks whether a point with @x, @y coordinates is contained
|
||||
* within @box
|
||||
*
|
||||
* Return value: %TRUE if the point is contained by the #ClutterActorBox
|
||||
*/
|
||||
gboolean
|
||||
clutter_actor_box_contains (const ClutterActorBox *box,
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
{
|
||||
g_return_val_if_fail (box != NULL, FALSE);
|
||||
|
||||
return (x > box->x1 && x < box->x2) &&
|
||||
(y > box->y1 && y < box->y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_from_vertices:
|
||||
* @box: a #ClutterActorBox
|
||||
* @verts: (array fixed-size=4): array of four #graphene_point3d_t
|
||||
*
|
||||
* Calculates the bounding box represented by the four vertices; for details
|
||||
* of the vertex array see [method@Actor.get_abs_allocation_vertices].
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_from_vertices (ClutterActorBox *box,
|
||||
const graphene_point3d_t verts[])
|
||||
{
|
||||
gfloat x_1, x_2, y_1, y_2;
|
||||
|
||||
g_return_if_fail (box != NULL);
|
||||
g_return_if_fail (verts != NULL);
|
||||
|
||||
/* 4-way min/max */
|
||||
x_1 = verts[0].x;
|
||||
y_1 = verts[0].y;
|
||||
|
||||
if (verts[1].x < x_1)
|
||||
x_1 = verts[1].x;
|
||||
|
||||
if (verts[2].x < x_1)
|
||||
x_1 = verts[2].x;
|
||||
|
||||
if (verts[3].x < x_1)
|
||||
x_1 = verts[3].x;
|
||||
|
||||
if (verts[1].y < y_1)
|
||||
y_1 = verts[1].y;
|
||||
|
||||
if (verts[2].y < y_1)
|
||||
y_1 = verts[2].y;
|
||||
|
||||
if (verts[3].y < y_1)
|
||||
y_1 = verts[3].y;
|
||||
|
||||
x_2 = verts[0].x;
|
||||
y_2 = verts[0].y;
|
||||
|
||||
if (verts[1].x > x_2)
|
||||
x_2 = verts[1].x;
|
||||
|
||||
if (verts[2].x > x_2)
|
||||
x_2 = verts[2].x;
|
||||
|
||||
if (verts[3].x > x_2)
|
||||
x_2 = verts[3].x;
|
||||
|
||||
if (verts[1].y > y_2)
|
||||
y_2 = verts[1].y;
|
||||
|
||||
if (verts[2].y > y_2)
|
||||
y_2 = verts[2].y;
|
||||
|
||||
if (verts[3].y > y_2)
|
||||
y_2 = verts[3].y;
|
||||
|
||||
box->x1 = x_1;
|
||||
box->x2 = x_2;
|
||||
box->y1 = y_1;
|
||||
box->y2 = y_2;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_interpolate:
|
||||
* @initial: the initial #ClutterActorBox
|
||||
* @final: the final #ClutterActorBox
|
||||
* @progress: the interpolation progress
|
||||
* @result: (out): return location for the interpolation
|
||||
*
|
||||
* Interpolates between @initial and @final `ClutterActorBox`es
|
||||
* using @progress
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_interpolate (const ClutterActorBox *initial,
|
||||
const ClutterActorBox *final,
|
||||
gdouble progress,
|
||||
ClutterActorBox *result)
|
||||
{
|
||||
g_return_if_fail (initial != NULL);
|
||||
g_return_if_fail (final != NULL);
|
||||
g_return_if_fail (result != NULL);
|
||||
|
||||
result->x1 = initial->x1 + (final->x1 - initial->x1) * progress;
|
||||
result->y1 = initial->y1 + (final->y1 - initial->y1) * progress;
|
||||
result->x2 = initial->x2 + (final->x2 - initial->x2) * progress;
|
||||
result->y2 = initial->y2 + (final->y2 - initial->y2) * progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_clamp_to_pixel:
|
||||
* @box: (inout): the #ClutterActorBox to clamp
|
||||
*
|
||||
* Clamps the components of @box to the nearest integer
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_clamp_to_pixel (ClutterActorBox *box)
|
||||
{
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
box->x1 = floorf (box->x1);
|
||||
box->y1 = floorf (box->y1);
|
||||
box->x2 = ceilf (box->x2);
|
||||
box->y2 = ceilf (box->y2);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_union:
|
||||
* @a: (in): the first #ClutterActorBox
|
||||
* @b: (in): the second #ClutterActorBox
|
||||
* @result: (out): the #ClutterActorBox representing a union
|
||||
* of @a and @b
|
||||
*
|
||||
* Unions the two boxes @a and @b and stores the result in @result.
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_union (const ClutterActorBox *a,
|
||||
const ClutterActorBox *b,
|
||||
ClutterActorBox *result)
|
||||
{
|
||||
g_return_if_fail (a != NULL);
|
||||
g_return_if_fail (b != NULL);
|
||||
g_return_if_fail (result != NULL);
|
||||
|
||||
result->x1 = MIN (a->x1, b->x1);
|
||||
result->y1 = MIN (a->y1, b->y1);
|
||||
|
||||
result->x2 = MAX (a->x2, b->x2);
|
||||
result->y2 = MAX (a->y2, b->y2);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_actor_box_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
gdouble factor,
|
||||
GValue *retval)
|
||||
{
|
||||
ClutterActorBox res = { 0, };
|
||||
|
||||
clutter_actor_box_interpolate (g_value_get_boxed (a),
|
||||
g_value_get_boxed (b),
|
||||
factor,
|
||||
&res);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_set_origin:
|
||||
* @box: a #ClutterActorBox
|
||||
* @x: the X coordinate of the new origin
|
||||
* @y: the Y coordinate of the new origin
|
||||
*
|
||||
* Changes the origin of @box, maintaining the size of the #ClutterActorBox.
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_set_origin (ClutterActorBox *box,
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
{
|
||||
gfloat width, height;
|
||||
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
width = box->x2 - box->x1;
|
||||
height = box->y2 - box->y1;
|
||||
|
||||
clutter_actor_box_init_rect (box, x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_set_size:
|
||||
* @box: a #ClutterActorBox
|
||||
* @width: the new width
|
||||
* @height: the new height
|
||||
*
|
||||
* Sets the size of @box, maintaining the origin of the #ClutterActorBox.
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_set_size (ClutterActorBox *box,
|
||||
gfloat width,
|
||||
gfloat height)
|
||||
{
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
box->x2 = box->x1 + width;
|
||||
box->y2 = box->y1 + height;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
|
||||
{
|
||||
float width, height;
|
||||
|
||||
if (clutter_actor_box_get_area (box) == 0.0)
|
||||
return;
|
||||
|
||||
/* The aim here is that for a given rectangle defined with floating point
|
||||
* coordinates we want to determine a stable quantized size in pixels
|
||||
* that doesn't vary due to the original box's sub-pixel position.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* The other thing we consider is that the calculation of this box is
|
||||
* subject to floating point precision issues that might be slightly
|
||||
* different to the precision issues involved with actually painting the
|
||||
* actor, which might result in painting slightly leaking outside the
|
||||
* user's calculated paint-volume. For this we simply aim to pad out the
|
||||
* paint-volume by at least half a pixel all the way around.
|
||||
*/
|
||||
width = box->x2 - box->x1;
|
||||
height = box->y2 - box->y1;
|
||||
width = CLUTTER_NEARBYINT (width);
|
||||
height = CLUTTER_NEARBYINT (height);
|
||||
/* XXX: NB the width/height may now be up to 0.5px too small so we
|
||||
* must also pad by 0.25px all around to account for this. In total we
|
||||
* must padd by at least 0.75px around all sides. */
|
||||
|
||||
/* XXX: The furthest that we can overshoot the bottom right corner by
|
||||
* here is 1.75px in total if you consider that the 0.75 padding could
|
||||
* just cross an integer boundary and so ceil will effectively add 1.
|
||||
*/
|
||||
box->x2 = ceilf (box->x2 + 0.75);
|
||||
box->y2 = ceilf (box->y2 + 0.75);
|
||||
|
||||
/* 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
|
||||
* position.
|
||||
*
|
||||
* Adding 3px to the width/height will ensure we cover the maximum of
|
||||
* 1.75px padding on the bottom/right and still ensure we have > 0.75px
|
||||
* padding on the top/left.
|
||||
*/
|
||||
box->x1 = box->x2 - width - 3;
|
||||
box->y1 = box->y2 - height - 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_scale:
|
||||
* @box: a #ClutterActorBox
|
||||
* @scale: scale factor for resizing this box
|
||||
*
|
||||
* Rescale the @box by provided @scale factor.
|
||||
*/
|
||||
void
|
||||
clutter_actor_box_scale (ClutterActorBox *box,
|
||||
gfloat scale)
|
||||
{
|
||||
g_return_if_fail (box != NULL);
|
||||
|
||||
box->x1 *= scale;
|
||||
box->x2 *= scale;
|
||||
box->y1 *= scale;
|
||||
box->y2 *= scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_box_is_initialized:
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Checks if @box has been initialized, a #ClutterActorBox is uninitialized
|
||||
* if it has a size of -1 at an origin of 0, 0.
|
||||
*
|
||||
* Returns: %TRUE if the box is uninitialized, %FALSE if it isn't
|
||||
*/
|
||||
gboolean
|
||||
clutter_actor_box_is_initialized (ClutterActorBox *box)
|
||||
{
|
||||
gboolean x1_uninitialized, x2_uninitialized;
|
||||
gboolean y1_uninitialized, y2_uninitialized;
|
||||
|
||||
g_return_val_if_fail (box != NULL, TRUE);
|
||||
|
||||
x1_uninitialized = isinf (box->x1);
|
||||
x2_uninitialized = isinf (box->x2) && signbit (box->x2);
|
||||
y1_uninitialized = isinf (box->y1);
|
||||
y2_uninitialized = isinf (box->y2) && signbit (box->y2);
|
||||
|
||||
return !x1_uninitialized || !x2_uninitialized ||
|
||||
!y1_uninitialized || !y2_uninitialized;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
|
||||
clutter_actor_box_copy,
|
||||
clutter_actor_box_free,
|
||||
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_actor_box_progress));
|
82
mutter/clutter/clutter/clutter-actor-meta-private.h
Normal file
82
mutter/clutter/clutter/clutter-actor-meta-private.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-actor-meta.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_META_GROUP (_clutter_meta_group_get_type ())
|
||||
|
||||
|
||||
struct _ClutterMetaGroup
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
ClutterActor *actor;
|
||||
|
||||
GList *meta;
|
||||
};
|
||||
|
||||
G_DECLARE_FINAL_TYPE (ClutterMetaGroup,
|
||||
_clutter_meta_group,
|
||||
CLUTTER, META_GROUP,
|
||||
GObject)
|
||||
|
||||
/* Each actor meta has a priority with zero as a default. A higher
|
||||
number means higher priority. Higher priority metas stay at the
|
||||
beginning of the list. The priority can be negative to give lower
|
||||
priority than the default. */
|
||||
|
||||
#define CLUTTER_ACTOR_META_PRIORITY_DEFAULT 0
|
||||
|
||||
/* Any value greater than this is considered an 'internal' priority
|
||||
and if we expose the priority property publicly then an application
|
||||
would not be able to use these values. */
|
||||
|
||||
#define CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH (G_MAXINT / 2)
|
||||
#define CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW (G_MININT / 2)
|
||||
|
||||
void _clutter_meta_group_add_meta (ClutterMetaGroup *group,
|
||||
ClutterActorMeta *meta);
|
||||
void _clutter_meta_group_remove_meta (ClutterMetaGroup *group,
|
||||
ClutterActorMeta *meta);
|
||||
const GList * _clutter_meta_group_peek_metas (ClutterMetaGroup *group);
|
||||
void _clutter_meta_group_clear_metas (ClutterMetaGroup *group);
|
||||
ClutterActorMeta * _clutter_meta_group_get_meta (ClutterMetaGroup *group,
|
||||
const gchar *name);
|
||||
|
||||
gboolean _clutter_meta_group_has_metas_no_internal (ClutterMetaGroup *group);
|
||||
|
||||
GList * _clutter_meta_group_get_metas_no_internal (ClutterMetaGroup *group);
|
||||
void _clutter_meta_group_clear_metas_no_internal (ClutterMetaGroup *group);
|
||||
|
||||
/* ActorMeta */
|
||||
const gchar * _clutter_actor_meta_get_debug_name (ClutterActorMeta *meta);
|
||||
|
||||
void _clutter_actor_meta_set_priority (ClutterActorMeta *meta,
|
||||
gint priority);
|
||||
|
||||
G_END_DECLS
|
702
mutter/clutter/clutter/clutter-actor-meta.c
Normal file
702
mutter/clutter/clutter/clutter-actor-meta.c
Normal file
@ -0,0 +1,702 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterActorMeta:
|
||||
*
|
||||
* Base class of actor modifiers
|
||||
*
|
||||
* #ClutterActorMeta is an abstract class providing a common API for
|
||||
* modifiers of [class@Actor] behaviour, appearance or layout.
|
||||
*
|
||||
* A #ClutterActorMeta can only be owned by a single [class@Actor] at
|
||||
* any time.
|
||||
*
|
||||
* Every sub-class of #ClutterActorMeta should check if the
|
||||
* [property@ActorMeta:enabled] property is set to %TRUE before applying
|
||||
* any kind of modification.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-actor-meta-private.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
struct _ClutterActorMetaPrivate
|
||||
{
|
||||
ClutterActor *actor;
|
||||
gulong destroy_id;
|
||||
|
||||
gchar *name;
|
||||
|
||||
guint is_enabled : 1;
|
||||
|
||||
gint priority;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_ACTOR,
|
||||
PROP_NAME,
|
||||
PROP_ENABLED,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterActorMeta,
|
||||
clutter_actor_meta,
|
||||
G_TYPE_INITIALLY_UNOWNED)
|
||||
|
||||
static void
|
||||
on_actor_destroy (ClutterActor *actor,
|
||||
ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
priv->actor = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_meta_real_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
g_warn_if_fail (!priv->actor ||
|
||||
!CLUTTER_ACTOR_IN_PAINT (priv->actor));
|
||||
g_warn_if_fail (!actor || !CLUTTER_ACTOR_IN_PAINT (actor));
|
||||
|
||||
if (priv->actor == actor)
|
||||
return;
|
||||
|
||||
g_clear_signal_handler (&priv->destroy_id, priv->actor);
|
||||
|
||||
priv->actor = actor;
|
||||
|
||||
if (priv->actor != NULL)
|
||||
priv->destroy_id = g_signal_connect (priv->actor, "destroy",
|
||||
G_CALLBACK (on_actor_destroy),
|
||||
meta);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ACTOR]);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_meta_real_set_enabled (ClutterActorMeta *meta,
|
||||
gboolean is_enabled)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
g_warn_if_fail (!priv->actor ||
|
||||
!CLUTTER_ACTOR_IN_PAINT (priv->actor));
|
||||
|
||||
priv->is_enabled = is_enabled;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_meta_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
clutter_actor_meta_set_name (meta, g_value_get_string (value));
|
||||
break;
|
||||
|
||||
case PROP_ENABLED:
|
||||
clutter_actor_meta_set_enabled (meta, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_meta_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (CLUTTER_ACTOR_META (gobject));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTOR:
|
||||
g_value_set_object (value, priv->actor);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, priv->name);
|
||||
break;
|
||||
|
||||
case PROP_ENABLED:
|
||||
g_value_set_boolean (value, priv->is_enabled);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_meta_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (CLUTTER_ACTOR_META (gobject));
|
||||
|
||||
if (priv->actor != NULL)
|
||||
g_clear_signal_handler (&priv->destroy_id, priv->actor);
|
||||
|
||||
g_free (priv->name);
|
||||
|
||||
G_OBJECT_CLASS (clutter_actor_meta_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_actor_meta_class_init (ClutterActorMetaClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->set_actor = clutter_actor_meta_real_set_actor;
|
||||
klass->set_enabled = clutter_actor_meta_real_set_enabled;
|
||||
|
||||
/**
|
||||
* ClutterActorMeta:actor:
|
||||
*
|
||||
* The #ClutterActor attached to the #ClutterActorMeta instance
|
||||
*/
|
||||
obj_props[PROP_ACTOR] =
|
||||
g_param_spec_object ("actor", NULL, NULL,
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* ClutterActorMeta:name:
|
||||
*
|
||||
* The unique name to access the #ClutterActorMeta
|
||||
*/
|
||||
obj_props[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterActorMeta:enabled:
|
||||
*
|
||||
* Whether or not the #ClutterActorMeta is enabled
|
||||
*/
|
||||
obj_props[PROP_ENABLED] =
|
||||
g_param_spec_boolean ("enabled", NULL, NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
gobject_class->finalize = clutter_actor_meta_finalize;
|
||||
gobject_class->set_property = clutter_actor_meta_set_property;
|
||||
gobject_class->get_property = clutter_actor_meta_get_property;
|
||||
g_object_class_install_properties (gobject_class,
|
||||
PROP_LAST,
|
||||
obj_props);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_actor_meta_init (ClutterActorMeta *self)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (self);
|
||||
|
||||
priv->is_enabled = TRUE;
|
||||
priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_meta_set_name:
|
||||
* @meta: a #ClutterActorMeta
|
||||
* @name: the name of @meta
|
||||
*
|
||||
* Sets the name of @meta
|
||||
*
|
||||
* The name can be used to identify the #ClutterActorMeta instance
|
||||
*/
|
||||
void
|
||||
clutter_actor_meta_set_name (ClutterActorMeta *meta,
|
||||
const gchar *name)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
if (g_strcmp0 (priv->name, name) == 0)
|
||||
return;
|
||||
|
||||
g_free (priv->name);
|
||||
priv->name = g_strdup (name);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_NAME]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_meta_get_name:
|
||||
* @meta: a #ClutterActorMeta
|
||||
*
|
||||
* Retrieves the name set using [method@ActorMeta.set_name]
|
||||
*
|
||||
* Return value: (transfer none): the name of the #ClutterActorMeta
|
||||
* instance, or %NULL if none was set. The returned string is owned
|
||||
* by the #ClutterActorMeta instance and it should not be modified
|
||||
* or freed
|
||||
*/
|
||||
const gchar *
|
||||
clutter_actor_meta_get_name (ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL);
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
return priv->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_meta_set_enabled:
|
||||
* @meta: a #ClutterActorMeta
|
||||
* @is_enabled: whether @meta is enabled
|
||||
*
|
||||
* Sets whether @meta should be enabled or not
|
||||
*/
|
||||
void
|
||||
clutter_actor_meta_set_enabled (ClutterActorMeta *meta,
|
||||
gboolean is_enabled)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
is_enabled = !!is_enabled;
|
||||
|
||||
if (priv->is_enabled == is_enabled)
|
||||
return;
|
||||
|
||||
CLUTTER_ACTOR_META_GET_CLASS (meta)->set_enabled (meta, is_enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_meta_get_enabled:
|
||||
* @meta: a #ClutterActorMeta
|
||||
*
|
||||
* Retrieves whether @meta is enabled
|
||||
*
|
||||
* Return value: %TRUE if the #ClutterActorMeta instance is enabled
|
||||
*/
|
||||
gboolean
|
||||
clutter_actor_meta_get_enabled (ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), FALSE);
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
return priv->is_enabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_actor_meta_set_actor
|
||||
* @meta: a #ClutterActorMeta
|
||||
* @actor: a #ClutterActor or %NULL
|
||||
*
|
||||
* Sets or unsets a back pointer to the #ClutterActor that owns
|
||||
* the @meta
|
||||
*/
|
||||
static void
|
||||
_clutter_actor_meta_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
|
||||
g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
CLUTTER_ACTOR_META_GET_CLASS (meta)->set_actor (meta, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_meta_get_actor:
|
||||
* @meta: a #ClutterActorMeta
|
||||
*
|
||||
* Retrieves a pointer to the [class@Actor] that owns @meta
|
||||
*
|
||||
* Return value: (transfer none): a pointer to a #ClutterActor or %NULL
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_actor_meta_get_actor (ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL);
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
return priv->actor;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_actor_meta_set_priority (ClutterActorMeta *meta,
|
||||
gint priority)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
/* This property shouldn't be modified after the actor meta is in
|
||||
use because ClutterMetaGroup doesn't resort the list when it
|
||||
changes. If we made the priority public then we could either make
|
||||
the priority a construct-only property or listen for
|
||||
notifications on the property from the ClutterMetaGroup and
|
||||
resort. */
|
||||
g_return_if_fail (priv->actor == NULL);
|
||||
|
||||
priv->priority = priority;
|
||||
}
|
||||
|
||||
static gint
|
||||
_clutter_actor_meta_get_priority (ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), 0);
|
||||
|
||||
priv = clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
return priv->priority;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_clutter_actor_meta_is_internal (ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
gint priority = priv->priority;
|
||||
|
||||
return (priority <= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW ||
|
||||
priority >= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH);
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterMetaGroup: a collection of ClutterActorMeta instances
|
||||
*/
|
||||
|
||||
G_DEFINE_FINAL_TYPE (ClutterMetaGroup, _clutter_meta_group, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
_clutter_meta_group_dispose (GObject *gobject)
|
||||
{
|
||||
_clutter_meta_group_clear_metas (CLUTTER_META_GROUP (gobject));
|
||||
|
||||
G_OBJECT_CLASS (_clutter_meta_group_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_meta_group_class_init (ClutterMetaGroupClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = _clutter_meta_group_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_meta_group_init (ClutterMetaGroup *self)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_add_meta:
|
||||
* @group: a #ClutterMetaGroup
|
||||
* @meta: a #ClutterActorMeta to add
|
||||
*
|
||||
* Adds @meta to @group
|
||||
*
|
||||
* This function will remove the floating reference of @meta or, if the
|
||||
* floating reference has already been sunk, add a reference to it
|
||||
*/
|
||||
void
|
||||
_clutter_meta_group_add_meta (ClutterMetaGroup *group,
|
||||
ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
GList *prev = NULL, *l;
|
||||
|
||||
if (priv->actor != NULL)
|
||||
{
|
||||
g_warning ("The meta of type '%s' with name '%s' is "
|
||||
"already attached to actor '%s'",
|
||||
G_OBJECT_TYPE_NAME (meta),
|
||||
priv->name != NULL
|
||||
? priv->name
|
||||
: "<unknown>",
|
||||
clutter_actor_get_name (priv->actor) != NULL
|
||||
? clutter_actor_get_name (priv->actor)
|
||||
: G_OBJECT_TYPE_NAME (priv->actor));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find a meta that has lower priority and insert before that */
|
||||
for (l = group->meta; l; l = l->next)
|
||||
if (_clutter_actor_meta_get_priority (l->data) <
|
||||
_clutter_actor_meta_get_priority (meta))
|
||||
break;
|
||||
else
|
||||
prev = l;
|
||||
|
||||
if (prev == NULL)
|
||||
group->meta = g_list_prepend (group->meta, meta);
|
||||
else
|
||||
{
|
||||
prev->next = g_list_prepend (prev->next, meta);
|
||||
prev->next->prev = prev;
|
||||
}
|
||||
|
||||
g_object_ref_sink (meta);
|
||||
|
||||
_clutter_actor_meta_set_actor (meta, group->actor);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_remove_meta:
|
||||
* @group: a #ClutterMetaGroup
|
||||
* @meta: a #ClutterActorMeta to remove
|
||||
*
|
||||
* Removes @meta from @group and releases the reference being held on it
|
||||
*/
|
||||
void
|
||||
_clutter_meta_group_remove_meta (ClutterMetaGroup *group,
|
||||
ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
if (priv->actor != group->actor)
|
||||
{
|
||||
g_warning ("The meta of type '%s' with name '%s' is not "
|
||||
"attached to the actor '%s'",
|
||||
G_OBJECT_TYPE_NAME (meta),
|
||||
priv->name != NULL
|
||||
? priv->name
|
||||
: "<unknown>",
|
||||
clutter_actor_get_name (group->actor) != NULL
|
||||
? clutter_actor_get_name (group->actor)
|
||||
: G_OBJECT_TYPE_NAME (group->actor));
|
||||
return;
|
||||
}
|
||||
|
||||
_clutter_actor_meta_set_actor (meta, NULL);
|
||||
|
||||
group->meta = g_list_remove (group->meta, meta);
|
||||
g_object_unref (meta);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_peek_metas:
|
||||
* @group: a #ClutterMetaGroup
|
||||
*
|
||||
* Returns a pointer to the #ClutterActorMeta list
|
||||
*
|
||||
* Return value: a const pointer to the #GList of #ClutterActorMeta
|
||||
*/
|
||||
const GList *
|
||||
_clutter_meta_group_peek_metas (ClutterMetaGroup *group)
|
||||
{
|
||||
return group->meta;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_get_metas_no_internal:
|
||||
* @group: a #ClutterMetaGroup
|
||||
*
|
||||
* Returns a new allocated list containing all of the metas that don't
|
||||
* have an internal priority.
|
||||
*
|
||||
* Return value: A GList containing non-internal metas. Free with
|
||||
* g_list_free.
|
||||
*/
|
||||
GList *
|
||||
_clutter_meta_group_get_metas_no_internal (ClutterMetaGroup *group)
|
||||
{
|
||||
GList *ret = NULL;
|
||||
GList *l;
|
||||
|
||||
/* Build a new list filtering out the internal metas */
|
||||
for (l = group->meta; l; l = l->next)
|
||||
if (!_clutter_actor_meta_is_internal (l->data))
|
||||
ret = g_list_prepend (ret, l->data);
|
||||
|
||||
return g_list_reverse (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_has_metas_no_internal:
|
||||
* @group: a #ClutterMetaGroup
|
||||
*
|
||||
* Returns whether the group has any metas that don't have an internal priority.
|
||||
*
|
||||
* Return value: %TRUE if metas without internal priority exist
|
||||
* %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
_clutter_meta_group_has_metas_no_internal (ClutterMetaGroup *group)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = group->meta; l; l = l->next)
|
||||
if (!_clutter_actor_meta_is_internal (l->data))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_clear_metas:
|
||||
* @group: a #ClutterMetaGroup
|
||||
*
|
||||
* Clears @group of all #ClutterActorMeta instances and releases
|
||||
* the reference on them
|
||||
*/
|
||||
void
|
||||
_clutter_meta_group_clear_metas (ClutterMetaGroup *group)
|
||||
{
|
||||
g_list_foreach (group->meta, (GFunc) _clutter_actor_meta_set_actor, NULL);
|
||||
|
||||
g_list_free_full (group->meta, g_object_unref);
|
||||
group->meta = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_clear_metas_no_internal:
|
||||
* @group: a #ClutterMetaGroup
|
||||
*
|
||||
* Clears @group of all #ClutterActorMeta instances that don't have an
|
||||
* internal priority and releases the reference on them
|
||||
*/
|
||||
void
|
||||
_clutter_meta_group_clear_metas_no_internal (ClutterMetaGroup *group)
|
||||
{
|
||||
GList *internal_list = NULL;
|
||||
GList *l, *next;
|
||||
|
||||
for (l = group->meta; l; l = next)
|
||||
{
|
||||
next = l->next;
|
||||
|
||||
if (_clutter_actor_meta_is_internal (l->data))
|
||||
{
|
||||
if (internal_list)
|
||||
internal_list->prev = l;
|
||||
l->next = internal_list;
|
||||
l->prev = NULL;
|
||||
internal_list = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
_clutter_actor_meta_set_actor (l->data, NULL);
|
||||
g_object_unref (l->data);
|
||||
g_list_free_1 (l);
|
||||
}
|
||||
}
|
||||
|
||||
group->meta = g_list_reverse (internal_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_meta_group_get_meta:
|
||||
* @group: a #ClutterMetaGroup
|
||||
* @name: the name of the #ClutterActorMeta to retrieve
|
||||
*
|
||||
* Retrieves a named #ClutterActorMeta from @group
|
||||
*
|
||||
* Return value: a #ClutterActorMeta for the given name, or %NULL
|
||||
*/
|
||||
ClutterActorMeta *
|
||||
_clutter_meta_group_get_meta (ClutterMetaGroup *group,
|
||||
const gchar *name)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = group->meta; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActorMeta *meta = l->data;
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
if (g_strcmp0 (priv->name, name) == 0)
|
||||
return meta;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_actor_meta_get_debug_name:
|
||||
* @meta: a #ClutterActorMeta
|
||||
*
|
||||
* Retrieves the name of the @meta for debugging purposes.
|
||||
*
|
||||
* Return value: (transfer none): the name of the @meta. The returned
|
||||
* string is owned by the @meta instance and it should not be
|
||||
* modified or freed
|
||||
*/
|
||||
const gchar *
|
||||
_clutter_actor_meta_get_debug_name (ClutterActorMeta *meta)
|
||||
{
|
||||
ClutterActorMetaPrivate *priv =
|
||||
clutter_actor_meta_get_instance_private (meta);
|
||||
|
||||
return priv->name != NULL ? priv->name : G_OBJECT_TYPE_NAME (meta);
|
||||
}
|
87
mutter/clutter/clutter/clutter-actor-meta.h
Normal file
87
mutter/clutter/clutter/clutter-actor-meta.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterActorMeta, clutter_actor_meta,
|
||||
CLUTTER, ACTOR_META, GInitiallyUnowned);
|
||||
|
||||
typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate;
|
||||
|
||||
/**
|
||||
* ClutterActorMetaClass:
|
||||
* @set_actor: virtual function, invoked when attaching and detaching
|
||||
* a #ClutterActorMeta instance to a #ClutterActor
|
||||
*
|
||||
* The #ClutterActorMetaClass structure contains
|
||||
* only private data
|
||||
*/
|
||||
struct _ClutterActorMetaClass
|
||||
{
|
||||
/*< private >*/
|
||||
GInitiallyUnownedClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
|
||||
/**
|
||||
* ClutterActorMetaClass::set_actor:
|
||||
* @meta: a #ClutterActorMeta
|
||||
* @actor: (allow-none): the actor attached to @meta, or %NULL
|
||||
*
|
||||
* Virtual function, called when @meta is attached or detached
|
||||
* from a #ClutterActor.
|
||||
*/
|
||||
void (* set_actor) (ClutterActorMeta *meta,
|
||||
ClutterActor *actor);
|
||||
|
||||
void (* set_enabled) (ClutterActorMeta *meta,
|
||||
gboolean is_enabled);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_meta_set_name (ClutterActorMeta *meta,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_actor_meta_get_name (ClutterActorMeta *meta);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_meta_set_enabled (ClutterActorMeta *meta,
|
||||
gboolean is_enabled);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_meta_get_enabled (ClutterActorMeta *meta);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_meta_get_actor (ClutterActorMeta *meta);
|
||||
|
||||
G_END_DECLS
|
271
mutter/clutter/clutter/clutter-actor-private.h
Normal file
271
mutter/clutter/clutter/clutter-actor-private.h
Normal file
@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-actor.h"
|
||||
#include "clutter/clutter-grab.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*< private >
|
||||
* ClutterActorTraverseFlags:
|
||||
* CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST: Traverse the graph in
|
||||
* a depth first order.
|
||||
* CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST: Traverse the graph in a
|
||||
* breadth first order.
|
||||
*
|
||||
* Controls some options for how clutter_actor_traverse() iterates
|
||||
* through the graph.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST = 1L<<0,
|
||||
CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST = 1L<<1
|
||||
} ClutterActorTraverseFlags;
|
||||
|
||||
/*< private >
|
||||
* ClutterActorTraverseVisitFlags:
|
||||
* CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE: Continue traversing as
|
||||
* normal
|
||||
* CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN: Don't traverse the
|
||||
* children of the last visited actor. (Not applicable when using
|
||||
* %CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST_POST_ORDER since the children
|
||||
* are visited before having an opportunity to bail out)
|
||||
* CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK: Immediately bail out without
|
||||
* visiting any more actors.
|
||||
*
|
||||
* Each time an actor is visited during a scenegraph traversal the
|
||||
* ClutterTraverseCallback can return a set of flags that may affect
|
||||
* the continuing traversal. It may stop traversal completely, just
|
||||
* skip over children for the current actor or continue as normal.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE = 1L<<0,
|
||||
CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN = 1L<<1,
|
||||
CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK = 1L<<2
|
||||
} ClutterActorTraverseVisitFlags;
|
||||
|
||||
/*< private >
|
||||
* ClutterTraverseCallback:
|
||||
*
|
||||
* The callback prototype used with clutter_actor_traverse. The
|
||||
* returned flags can be used to affect the continuing traversal
|
||||
* either by continuing as normal, skipping over children of an
|
||||
* actor or bailing out completely.
|
||||
*/
|
||||
typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor *actor,
|
||||
gint depth,
|
||||
gpointer user_data);
|
||||
|
||||
/*< private >
|
||||
* ClutterForeachCallback:
|
||||
* @actor: The actor being iterated
|
||||
* @user_data: The private data specified when starting the iteration
|
||||
*
|
||||
* A generic callback for iterating over actor, such as with
|
||||
* _clutter_actor_foreach_child.
|
||||
*
|
||||
* Return value: %TRUE to continue iterating or %FALSE to break iteration
|
||||
* early.
|
||||
*/
|
||||
typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _SizeRequest SizeRequest;
|
||||
|
||||
typedef struct _ClutterLayoutInfo ClutterLayoutInfo;
|
||||
typedef struct _ClutterTransformInfo ClutterTransformInfo;
|
||||
typedef struct _ClutterAnimationInfo ClutterAnimationInfo;
|
||||
|
||||
struct _SizeRequest
|
||||
{
|
||||
guint age;
|
||||
gfloat for_size;
|
||||
gfloat min_size;
|
||||
gfloat natural_size;
|
||||
};
|
||||
|
||||
/*< private >
|
||||
* ClutterLayoutInfo:
|
||||
* @fixed_pos: the fixed position of the actor
|
||||
* @margin: the composed margin of the actor
|
||||
* @x_align: the horizontal alignment, if the actor expands horizontally
|
||||
* @y_align: the vertical alignment, if the actor expands vertically
|
||||
* @x_expand: whether the actor should expand horizontally
|
||||
* @y_expand: whether the actor should expand vertically
|
||||
* @minimum: the fixed minimum size
|
||||
* @natural: the fixed natural size
|
||||
*
|
||||
* Ancillary layout information for an actor.
|
||||
*/
|
||||
struct _ClutterLayoutInfo
|
||||
{
|
||||
/* fixed position coordinates */
|
||||
graphene_point_t fixed_pos;
|
||||
|
||||
ClutterMargin margin;
|
||||
|
||||
guint x_align : 4;
|
||||
guint y_align : 4;
|
||||
|
||||
guint x_expand : 1;
|
||||
guint y_expand : 1;
|
||||
|
||||
graphene_size_t minimum;
|
||||
graphene_size_t natural;
|
||||
};
|
||||
|
||||
const ClutterLayoutInfo * _clutter_actor_get_layout_info_or_defaults (ClutterActor *self);
|
||||
ClutterLayoutInfo * _clutter_actor_get_layout_info (ClutterActor *self);
|
||||
ClutterLayoutInfo * _clutter_actor_peek_layout_info (ClutterActor *self);
|
||||
|
||||
struct _ClutterTransformInfo
|
||||
{
|
||||
/* rotation */
|
||||
gdouble rx_angle;
|
||||
gdouble ry_angle;
|
||||
gdouble rz_angle;
|
||||
|
||||
/* scaling */
|
||||
gdouble scale_x;
|
||||
gdouble scale_y;
|
||||
gdouble scale_z;
|
||||
|
||||
/* translation */
|
||||
graphene_point3d_t translation;
|
||||
|
||||
/* z_position */
|
||||
gfloat z_position;
|
||||
|
||||
/* transformation center */
|
||||
graphene_point_t pivot;
|
||||
gfloat pivot_z;
|
||||
|
||||
graphene_matrix_t transform;
|
||||
guint transform_set : 1;
|
||||
|
||||
graphene_matrix_t child_transform;
|
||||
guint child_transform_set : 1;
|
||||
};
|
||||
|
||||
const ClutterTransformInfo * _clutter_actor_get_transform_info_or_defaults (ClutterActor *self);
|
||||
ClutterTransformInfo * _clutter_actor_get_transform_info (ClutterActor *self);
|
||||
|
||||
typedef struct _AState {
|
||||
guint easing_duration;
|
||||
guint easing_delay;
|
||||
ClutterAnimationMode easing_mode;
|
||||
} AState;
|
||||
|
||||
struct _ClutterAnimationInfo
|
||||
{
|
||||
GArray *states;
|
||||
AState *cur_state;
|
||||
|
||||
GHashTable *transitions;
|
||||
};
|
||||
|
||||
const ClutterAnimationInfo * _clutter_actor_get_animation_info_or_defaults (ClutterActor *self);
|
||||
ClutterAnimationInfo * _clutter_actor_get_animation_info (ClutterActor *self);
|
||||
|
||||
ClutterTransition * _clutter_actor_create_transition (ClutterActor *self,
|
||||
GParamSpec *pspec,
|
||||
...);
|
||||
gboolean _clutter_actor_foreach_child (ClutterActor *self,
|
||||
ClutterForeachCallback callback,
|
||||
gpointer user_data);
|
||||
void _clutter_actor_traverse (ClutterActor *actor,
|
||||
ClutterActorTraverseFlags flags,
|
||||
ClutterTraverseCallback before_children_callback,
|
||||
ClutterTraverseCallback after_children_callback,
|
||||
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_set_in_clone_paint (ClutterActor *self,
|
||||
gboolean is_in_clone_paint);
|
||||
|
||||
void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
|
||||
gboolean enable);
|
||||
|
||||
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
||||
gboolean enable);
|
||||
|
||||
void _clutter_actor_set_has_pointer (ClutterActor *self,
|
||||
gboolean has_pointer);
|
||||
|
||||
void _clutter_actor_set_has_key_focus (ClutterActor *self,
|
||||
gboolean has_key_focus);
|
||||
|
||||
void _clutter_actor_queue_redraw_full (ClutterActor *self,
|
||||
const ClutterPaintVolume *volume,
|
||||
ClutterEffect *effect);
|
||||
|
||||
gboolean _clutter_actor_set_default_paint_volume (ClutterActor *self,
|
||||
GType check_gtype,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
const char * _clutter_actor_get_debug_name (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_push_clone_paint (void);
|
||||
void _clutter_actor_pop_clone_paint (void);
|
||||
|
||||
ClutterActorAlign _clutter_actor_get_effective_x_align (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_attach_clone (ClutterActor *actor,
|
||||
ClutterActor *clone);
|
||||
void _clutter_actor_detach_clone (ClutterActor *actor,
|
||||
ClutterActor *clone);
|
||||
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
|
||||
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor,
|
||||
gboolean stop_transitions);
|
||||
|
||||
float clutter_actor_get_real_resource_scale (ClutterActor *actor);
|
||||
|
||||
void clutter_actor_finish_layout (ClutterActor *self,
|
||||
int phase);
|
||||
|
||||
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
|
||||
|
||||
gboolean clutter_actor_is_painting_unmapped (ClutterActor *self);
|
||||
|
||||
void clutter_actor_attach_grab (ClutterActor *actor,
|
||||
ClutterGrab *grab);
|
||||
void clutter_actor_detach_grab (ClutterActor *actor,
|
||||
ClutterGrab *grab);
|
||||
|
||||
void clutter_actor_collect_event_actors (ClutterActor *self,
|
||||
ClutterActor *deepmost,
|
||||
GPtrArray *actors);
|
||||
|
||||
const GList * clutter_actor_peek_actions (ClutterActor *self);
|
||||
|
||||
void clutter_actor_set_implicitly_grabbed (ClutterActor *actor,
|
||||
gboolean is_implicitly_grabbed);
|
||||
|
||||
G_END_DECLS
|
18606
mutter/clutter/clutter/clutter-actor.c
Normal file
18606
mutter/clutter/clutter/clutter-actor.c
Normal file
File diff suppressed because it is too large
Load Diff
882
mutter/clutter/clutter/clutter-actor.h
Normal file
882
mutter/clutter/clutter/clutter-actor.h
Normal file
@ -0,0 +1,882 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
|
||||
* Copyright (C) 2009, 2010 Intel Corp
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
/* clutter-actor.h */
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <pango/pango.h>
|
||||
#include <atk/atk.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
#include "clutter/clutter-event.h"
|
||||
#include "clutter/clutter-paint-context.h"
|
||||
#include "clutter/clutter-pick-context.h"
|
||||
#include "mtk/mtk.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_ACTOR (clutter_actor_get_type ())
|
||||
#define CLUTTER_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR, ClutterActor))
|
||||
#define CLUTTER_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR, ClutterActorClass))
|
||||
#define CLUTTER_IS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR))
|
||||
#define CLUTTER_IS_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR))
|
||||
#define CLUTTER_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR, ClutterActorClass))
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActor, g_object_unref)
|
||||
|
||||
typedef struct _ClutterActorClass ClutterActorClass;
|
||||
typedef struct _ClutterActorPrivate ClutterActorPrivate;
|
||||
|
||||
|
||||
struct _ClutterActor
|
||||
{
|
||||
/*< private >*/
|
||||
GInitiallyUnowned parent_instance;
|
||||
|
||||
/*< public >*/
|
||||
guint32 flags;
|
||||
|
||||
/*< private >*/
|
||||
guint32 private_flags;
|
||||
|
||||
ClutterActorPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterActorClass:
|
||||
* @show: signal class handler for [signal@Clutter.Actor::show]; it must chain
|
||||
* up to the parent's implementation
|
||||
* @hide: signal class handler for [signal@Clutter.Actor::hide]; it must chain
|
||||
* up to the parent's implementation
|
||||
* @hide_all: virtual function for containers and composite actors, to
|
||||
* determine which children should be shown when calling
|
||||
* clutter_actor_hide_all() on the actor. Defaults to calling
|
||||
* clutter_actor_hide(). This virtual function is deprecated and it
|
||||
* should not be overridden.
|
||||
* @realize: virtual function, used to allocate resources for the actor;
|
||||
* it should chain up to the parent's implementation. This virtual
|
||||
* function is deprecated and should not be overridden in newly
|
||||
* written code.
|
||||
* @unrealize: virtual function, used to deallocate resources allocated
|
||||
* in ::realize; it should chain up to the parent's implementation. This
|
||||
* function is deprecated and should not be overridden in newly
|
||||
* written code.
|
||||
* @map: virtual function for containers and composite actors, to
|
||||
* map their children; it must chain up to the parent's implementation.
|
||||
* Overriding this function is optional.
|
||||
* @unmap: virtual function for containers and composite actors, to
|
||||
* unmap their children; it must chain up to the parent's implementation.
|
||||
* Overriding this function is optional.
|
||||
* @paint: virtual function, used to paint the actor
|
||||
* @get_preferred_width: virtual function, used when querying the minimum
|
||||
* and natural widths of an actor for a given height; it is used by
|
||||
* clutter_actor_get_preferred_width()
|
||||
* @get_preferred_height: virtual function, used when querying the minimum
|
||||
* and natural heights of an actor for a given width; it is used by
|
||||
* clutter_actor_get_preferred_height()
|
||||
* @allocate: virtual function, used when setting the coordinates of an
|
||||
* actor; it is used by clutter_actor_allocate(); when overriding this
|
||||
* function without chaining up, clutter_actor_set_allocation() must be
|
||||
* called and children must be allocated by the implementation, when
|
||||
* chaining up though, those things will be done by the parent's
|
||||
* implementation.
|
||||
* @apply_transform: virtual function, used when applying the transformations
|
||||
* to an actor before painting it or when transforming coordinates or
|
||||
* the allocation; if the transformation calculated by this function may
|
||||
* have changed, the cached transformation must be invalidated by calling
|
||||
* clutter_actor_invalidate_transform(); it must chain up to the parent's
|
||||
* implementation
|
||||
* @parent_set: signal class handler for the [signal@Clutter.Actor::parent-set]
|
||||
* @destroy: signal class handler for [signal@Clutter.Actor::destroy]. It must
|
||||
* chain up to the parent's implementation
|
||||
* @pick: virtual function, used to draw an outline of the actor with
|
||||
* the given color
|
||||
* @event: class handler for [signal@Clutter.Actor::event]
|
||||
* @button_press_event: class handler for [signal@Clutter.Actor::button-press-event]
|
||||
* @button_release_event: class handler for
|
||||
* [signal@Clutter.Actor::button-release-event]
|
||||
* @scroll_event: signal class closure for [signal@Clutter.Actor::scroll-event]
|
||||
* @key_press_event: signal class closure for [signal@Clutter.Actor::key-press-event]
|
||||
* @key_release_event: signal class closure for
|
||||
* [signal@Clutter.Actor::key-release-event]
|
||||
* @motion_event: signal class closure for [signal@Clutter.Actor::motion-event]
|
||||
* @enter_event: signal class closure for [signal@Clutter.Actor::enter-event]
|
||||
* @leave_event: signal class closure for [signal@Clutter.Actor::leave-event]
|
||||
* @captured_event: signal class closure for [signal@Clutter.Actor::captured-event]
|
||||
* @key_focus_in: signal class closure for [signal@Clutter.Actor::key-focus-in]
|
||||
* @key_focus_out: signal class closure for [signal@Clutter.Actor::key-focus-out]
|
||||
* @queue_relayout: class handler for [signal@Clutter.Actor::queue-relayout]
|
||||
* @get_accessible: virtual function, returns the accessible object that
|
||||
* describes the actor to an assistive technology.
|
||||
* @get_paint_volume: virtual function, for sub-classes to define their
|
||||
* #ClutterPaintVolume
|
||||
* @has_overlaps: virtual function for
|
||||
* sub-classes to advertise whether they need an offscreen redirect
|
||||
* to get the correct opacity. See
|
||||
* clutter_actor_set_offscreen_redirect() for details.
|
||||
* @paint_node: virtual function for creating paint nodes and attaching
|
||||
* them to the render tree
|
||||
* @touch_event: signal class closure for [signal@Clutter.Actor::touch-event]
|
||||
*
|
||||
* Base class for actors.
|
||||
*/
|
||||
struct _ClutterActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
GInitiallyUnownedClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (* show) (ClutterActor *self);
|
||||
void (* hide) (ClutterActor *self);
|
||||
void (* hide_all) (ClutterActor *self);
|
||||
void (* realize) (ClutterActor *self);
|
||||
void (* unrealize) (ClutterActor *self);
|
||||
void (* map) (ClutterActor *self);
|
||||
void (* unmap) (ClutterActor *self);
|
||||
void (* paint) (ClutterActor *self,
|
||||
ClutterPaintContext *paint_context);
|
||||
void (* parent_set) (ClutterActor *actor,
|
||||
ClutterActor *old_parent);
|
||||
|
||||
void (* destroy) (ClutterActor *self);
|
||||
void (* pick) (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context);
|
||||
|
||||
/* size negotiation */
|
||||
void (* get_preferred_width) (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p);
|
||||
void (* get_preferred_height) (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p);
|
||||
void (* allocate) (ClutterActor *self,
|
||||
const ClutterActorBox *box);
|
||||
|
||||
/* transformations */
|
||||
void (* apply_transform) (ClutterActor *actor,
|
||||
graphene_matrix_t *matrix);
|
||||
|
||||
/* event signals */
|
||||
gboolean (* event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* button_press_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* button_release_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* scroll_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* key_press_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* key_release_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* motion_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* enter_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* leave_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
gboolean (* captured_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
void (* key_focus_in) (ClutterActor *actor);
|
||||
void (* key_focus_out) (ClutterActor *actor);
|
||||
|
||||
void (* queue_relayout) (ClutterActor *self);
|
||||
|
||||
/* accessibility support */
|
||||
AtkObject * (* get_accessible) (ClutterActor *self);
|
||||
|
||||
gboolean (* get_paint_volume) (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
gboolean (* has_overlaps) (ClutterActor *self);
|
||||
|
||||
void (* paint_node) (ClutterActor *self,
|
||||
ClutterPaintNode *root);
|
||||
|
||||
gboolean (* touch_event) (ClutterActor *self,
|
||||
ClutterEvent *event);
|
||||
gboolean (* has_accessible) (ClutterActor *self);
|
||||
void (* resource_scale_changed) (ClutterActor *self);
|
||||
float (* calculate_resource_scale) (ClutterActor *self,
|
||||
int phase);
|
||||
|
||||
void (* child_added) (ClutterActor *self,
|
||||
ClutterActor *child);
|
||||
void (* child_removed) (ClutterActor *self,
|
||||
ClutterActor *child);
|
||||
|
||||
/* private */
|
||||
GType layout_manager_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterActorIter:
|
||||
*
|
||||
* An iterator structure that allows to efficiently iterate over a
|
||||
* section of the scene graph.
|
||||
*
|
||||
* The contents of the #ClutterActorIter structure
|
||||
* are private and should only be accessed using the provided API.
|
||||
*/
|
||||
struct _ClutterActorIter
|
||||
{
|
||||
/*< private >*/
|
||||
gpointer CLUTTER_PRIVATE_FIELD (dummy1);
|
||||
gpointer CLUTTER_PRIVATE_FIELD (dummy2);
|
||||
gint CLUTTER_PRIVATE_FIELD (dummy3);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_actor_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_new (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_flags (ClutterActor *self,
|
||||
ClutterActorFlags flags);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_unset_flags (ClutterActor *self,
|
||||
ClutterActorFlags flags);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActorFlags clutter_actor_get_flags (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_show (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_hide (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_realize (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_unrealize (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_map (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_unmap (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_paint (ClutterActor *self,
|
||||
ClutterPaintContext *paint_context);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_continue_paint (ClutterActor *self,
|
||||
ClutterPaintContext *paint_context);
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
|
||||
CoglTexture *texture);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_pick (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_continue_pick (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_queue_redraw (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
const MtkRectangle *clip);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_queue_relayout (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_destroy (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_name (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_actor_get_name (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
AtkObject * clutter_actor_get_accessible (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_accessible (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_visible (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_mapped (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_realized (ClutterActor *self);
|
||||
|
||||
/* Size negotiation */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_request_mode (ClutterActor *self,
|
||||
ClutterRequestMode mode);
|
||||
CLUTTER_EXPORT
|
||||
ClutterRequestMode clutter_actor_get_request_mode (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_preferred_size (ClutterActor *self,
|
||||
gfloat *min_width_p,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_width_p,
|
||||
gfloat *natural_height_p);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self,
|
||||
float x,
|
||||
float y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_available_size (ClutterActor *self,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat available_width,
|
||||
gfloat available_height);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_align_fill (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gdouble x_align,
|
||||
gdouble y_align,
|
||||
gboolean x_fill,
|
||||
gboolean y_fill);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_allocation (ClutterActor *self,
|
||||
const ClutterActorBox *box);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_allocation_box (ClutterActor *self,
|
||||
ClutterActorBox *box);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_allocation (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_size (ClutterActor *self,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_size (ClutterActor *self,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_position (ClutterActor *self,
|
||||
gfloat x,
|
||||
gfloat y);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_fixed_position (ClutterActor *self,
|
||||
float *x,
|
||||
float *y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_position (ClutterActor *self,
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_fixed_position_set (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_fixed_position_set (ClutterActor *self,
|
||||
gboolean is_set);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_move_by (ClutterActor *self,
|
||||
gfloat dx,
|
||||
gfloat dy);
|
||||
|
||||
/* Actor geometry */
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_width (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_height (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_width (ClutterActor *self,
|
||||
gfloat width);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_height (ClutterActor *self,
|
||||
gfloat height);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_x (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_y (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_x (ClutterActor *self,
|
||||
gfloat x);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_y (ClutterActor *self,
|
||||
gfloat y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_z_position (ClutterActor *self,
|
||||
gfloat z_position);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_z_position (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_layout_manager (ClutterActor *self,
|
||||
ClutterLayoutManager *manager);
|
||||
CLUTTER_EXPORT
|
||||
ClutterLayoutManager * clutter_actor_get_layout_manager (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_x_align (ClutterActor *self,
|
||||
ClutterActorAlign x_align);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActorAlign clutter_actor_get_x_align (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_y_align (ClutterActor *self,
|
||||
ClutterActorAlign y_align);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActorAlign clutter_actor_get_y_align (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_margin_top (ClutterActor *self,
|
||||
gfloat margin);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_margin_top (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_margin_bottom (ClutterActor *self,
|
||||
gfloat margin);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_margin_bottom (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_margin_left (ClutterActor *self,
|
||||
gfloat margin);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_margin_left (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_margin_right (ClutterActor *self,
|
||||
gfloat margin);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_margin_right (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_margin (ClutterActor *self,
|
||||
const ClutterMargin *margin);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_margin (ClutterActor *self,
|
||||
ClutterMargin *margin);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_x_expand (ClutterActor *self,
|
||||
gboolean expand);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_x_expand (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_y_expand (ClutterActor *self,
|
||||
gboolean expand);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_y_expand (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_needs_expand (ClutterActor *self,
|
||||
ClutterOrientation orientation);
|
||||
|
||||
/* Paint */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_clip (ClutterActor *self,
|
||||
gfloat xoff,
|
||||
gfloat yoff,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_clip (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_clip (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_clip (ClutterActor *self,
|
||||
gfloat *xoff,
|
||||
gfloat *yoff,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_clip_to_allocation (ClutterActor *self,
|
||||
gboolean clip_set);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_clip_to_allocation (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_opacity (ClutterActor *self,
|
||||
guint8 opacity);
|
||||
CLUTTER_EXPORT
|
||||
guint8 clutter_actor_get_opacity (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
guint8 clutter_actor_get_paint_opacity (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_paint_visibility (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_offscreen_redirect (ClutterActor *self,
|
||||
ClutterOffscreenRedirect redirect);
|
||||
CLUTTER_EXPORT
|
||||
ClutterOffscreenRedirect clutter_actor_get_offscreen_redirect (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_should_pick (ClutterActor *self,
|
||||
ClutterPickContext *pick_context);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_paint_box (ClutterActor *self,
|
||||
ClutterActorBox *box);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
float clutter_actor_get_resource_scale (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_overlaps (ClutterActor *self);
|
||||
|
||||
/* Content */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_content (ClutterActor *self,
|
||||
ClutterContent *content);
|
||||
CLUTTER_EXPORT
|
||||
ClutterContent * clutter_actor_get_content (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_content_gravity (ClutterActor *self,
|
||||
ClutterContentGravity gravity);
|
||||
CLUTTER_EXPORT
|
||||
ClutterContentGravity clutter_actor_get_content_gravity (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_content_scaling_filters (ClutterActor *self,
|
||||
ClutterScalingFilter min_filter,
|
||||
ClutterScalingFilter mag_filter);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_content_scaling_filters (ClutterActor *self,
|
||||
ClutterScalingFilter *min_filter,
|
||||
ClutterScalingFilter *mag_filter);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_content_repeat (ClutterActor *self,
|
||||
ClutterContentRepeat repeat);
|
||||
CLUTTER_EXPORT
|
||||
ClutterContentRepeat clutter_actor_get_content_repeat (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_color_state (ClutterActor *self,
|
||||
ClutterColorState *color_state);
|
||||
CLUTTER_EXPORT
|
||||
ClutterColorState *clutter_actor_get_color_state (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_content_box (ClutterActor *self,
|
||||
ClutterActorBox *box);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_background_color (ClutterActor *self,
|
||||
const ClutterColor *color);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_background_color (ClutterActor *self,
|
||||
ClutterColor *color);
|
||||
CLUTTER_EXPORT
|
||||
const ClutterPaintVolume * clutter_actor_get_paint_volume (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintVolume * clutter_actor_get_transformed_paint_volume (ClutterActor *self,
|
||||
ClutterActor *relative_to_ancestor);
|
||||
|
||||
/* Events */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_reactive (ClutterActor *actor,
|
||||
gboolean reactive);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_reactive (ClutterActor *actor);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_key_focus (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_grab_key_focus (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_event (ClutterActor *actor,
|
||||
const ClutterEvent *event,
|
||||
gboolean capture);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_pointer (ClutterActor *self);
|
||||
|
||||
/* Text */
|
||||
CLUTTER_EXPORT
|
||||
PangoContext * clutter_actor_get_pango_context (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
PangoContext * clutter_actor_create_pango_context (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
PangoLayout * clutter_actor_create_pango_layout (ClutterActor *self,
|
||||
const gchar *text);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_text_direction (ClutterActor *self,
|
||||
ClutterTextDirection text_dir);
|
||||
CLUTTER_EXPORT
|
||||
ClutterTextDirection clutter_actor_get_text_direction (ClutterActor *self);
|
||||
|
||||
/* Actor hierarchy */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_child (ClutterActor *self,
|
||||
ClutterActor *child);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_insert_child_at_index (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
gint index_);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_insert_child_above (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
ClutterActor *sibling);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_insert_child_below (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
ClutterActor *sibling);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_replace_child (ClutterActor *self,
|
||||
ClutterActor *old_child,
|
||||
ClutterActor *new_child);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_child (ClutterActor *self,
|
||||
ClutterActor *child);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_all_children (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_destroy_all_children (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_actor_get_children (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_actor_get_n_children (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_get_child_at_index (ClutterActor *self,
|
||||
gint index_);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_get_previous_sibling (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_get_next_sibling (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_get_first_child (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_get_last_child (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_actor_get_parent (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_contains (ClutterActor *self,
|
||||
ClutterActor *descendant);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor* clutter_actor_get_stage (ClutterActor *actor);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_child_below_sibling (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
ClutterActor *sibling);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_child_above_sibling (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
ClutterActor *sibling);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_child_at_index (ClutterActor *self,
|
||||
ClutterActor *child,
|
||||
gint index_);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_iter_init (ClutterActorIter *iter,
|
||||
ClutterActor *root);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_iter_next (ClutterActorIter *iter,
|
||||
ClutterActor **child);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_iter_prev (ClutterActorIter *iter,
|
||||
ClutterActor **child);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_iter_remove (ClutterActorIter *iter);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_iter_destroy (ClutterActorIter *iter);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_iter_is_valid (const ClutterActorIter *iter);
|
||||
|
||||
/* Transformations */
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_rotated (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_scaled (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_pivot_point (ClutterActor *self,
|
||||
gfloat pivot_x,
|
||||
gfloat pivot_y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_pivot_point (ClutterActor *self,
|
||||
gfloat *pivot_x,
|
||||
gfloat *pivot_y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_pivot_point_z (ClutterActor *self,
|
||||
gfloat pivot_z);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_actor_get_pivot_point_z (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_rotation_angle (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
gdouble angle);
|
||||
CLUTTER_EXPORT
|
||||
gdouble clutter_actor_get_rotation_angle (ClutterActor *self,
|
||||
ClutterRotateAxis axis);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_scale (ClutterActor *self,
|
||||
gdouble scale_x,
|
||||
gdouble scale_y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_scale (ClutterActor *self,
|
||||
gdouble *scale_x,
|
||||
gdouble *scale_y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_scale_z (ClutterActor *self,
|
||||
gdouble scale_z);
|
||||
CLUTTER_EXPORT
|
||||
gdouble clutter_actor_get_scale_z (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_translation (ClutterActor *self,
|
||||
gfloat translate_x,
|
||||
gfloat translate_y,
|
||||
gfloat translate_z);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_translation (ClutterActor *self,
|
||||
gfloat *translate_x,
|
||||
gfloat *translate_y,
|
||||
gfloat *translate_z);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_transform (ClutterActor *self,
|
||||
const graphene_matrix_t *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transform (ClutterActor *self,
|
||||
graphene_matrix_t *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_child_transform (ClutterActor *self,
|
||||
const graphene_matrix_t *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_child_transform (ClutterActor *self,
|
||||
graphene_matrix_t *transform);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transformed_extents (ClutterActor *self,
|
||||
graphene_rect_t *rect);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transformed_position (ClutterActor *self,
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transformed_size (ClutterActor *self,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_transform_stage_point (ClutterActor *self,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat *x_out,
|
||||
gfloat *y_out);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
|
||||
graphene_point3d_t *verts);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_apply_transform_to_point (ClutterActor *self,
|
||||
const graphene_point3d_t *point,
|
||||
graphene_point3d_t *vertex);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
|
||||
ClutterActor *ancestor,
|
||||
const graphene_point3d_t *point,
|
||||
graphene_point3d_t *vertex);
|
||||
|
||||
/* Implicit animations */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_save_easing_state (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_restore_easing_state (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_easing_mode (ClutterActor *self,
|
||||
ClutterAnimationMode mode);
|
||||
CLUTTER_EXPORT
|
||||
ClutterAnimationMode clutter_actor_get_easing_mode (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_easing_duration (ClutterActor *self,
|
||||
guint msecs);
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_actor_get_easing_duration (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_easing_delay (ClutterActor *self,
|
||||
guint msecs);
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_actor_get_easing_delay (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterTransition * clutter_actor_get_transition (ClutterActor *self,
|
||||
const char *name);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_transition (ClutterActor *self,
|
||||
const char *name,
|
||||
ClutterTransition *transition);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_transition (ClutterActor *self,
|
||||
const char *name);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_all_transitions (ClutterActor *self);
|
||||
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_mapped_clones (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_opacity_override (ClutterActor *self,
|
||||
gint opacity);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_actor_get_opacity_override (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_inhibit_culling (ClutterActor *actor);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_uninhibit_culling (ClutterActor *actor);
|
||||
|
||||
/**
|
||||
* ClutterActorCreateChildFunc:
|
||||
* @item: (type GObject): the item in the model
|
||||
* @user_data: Data passed to clutter_actor_bind_model()
|
||||
*
|
||||
* Creates a #ClutterActor using the @item in the model.
|
||||
*
|
||||
* The usual way to implement this function is to create a #ClutterActor
|
||||
* instance and then bind the #GObject properties to the actor properties
|
||||
* of interest, using g_object_bind_property(). This way, when the @item
|
||||
* in the #GListModel changes, the #ClutterActor changes as well.
|
||||
*
|
||||
* Returns: (transfer full): The newly created child #ClutterActor4
|
||||
*/
|
||||
typedef ClutterActor * (* ClutterActorCreateChildFunc) (gpointer item,
|
||||
gpointer user_data);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_bind_model (ClutterActor *self,
|
||||
GListModel *model,
|
||||
ClutterActorCreateChildFunc create_child_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify notify);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_bind_model_with_properties (ClutterActor *self,
|
||||
GListModel *model,
|
||||
GType child_type,
|
||||
const char *first_model_property,
|
||||
...);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_pick_box (ClutterActor *self,
|
||||
ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
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);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_class_set_layout_manager_type (ClutterActorClass *actor_class,
|
||||
GType type);
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_actor_class_get_layout_manager_type (ClutterActorClass *actor_class);
|
||||
|
||||
G_END_DECLS
|
607
mutter/clutter/clutter/clutter-align-constraint.c
Normal file
607
mutter/clutter/clutter/clutter-align-constraint.c
Normal file
@ -0,0 +1,607 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterAlignConstraint:
|
||||
*
|
||||
* A constraint aligning the position of an actor
|
||||
*
|
||||
* #ClutterAlignConstraint is a [class@Constraint] that aligns the position
|
||||
* of the [class@Actor] to which it is applied to the size of another
|
||||
* [class@Actor] using an alignment factor
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-align-constraint.h"
|
||||
|
||||
#include "clutter/clutter-actor-meta-private.h"
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#include "clutter/clutter-constraint.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
struct _ClutterAlignConstraint
|
||||
{
|
||||
ClutterConstraint parent_instance;
|
||||
|
||||
ClutterActor *actor;
|
||||
ClutterActor *source;
|
||||
ClutterAlignAxis align_axis;
|
||||
graphene_point_t pivot;
|
||||
gfloat factor;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_SOURCE,
|
||||
PROP_ALIGN_AXIS,
|
||||
PROP_PIVOT_POINT,
|
||||
PROP_FACTOR,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_FINAL_TYPE (ClutterAlignConstraint,
|
||||
clutter_align_constraint,
|
||||
CLUTTER_TYPE_CONSTRAINT);
|
||||
|
||||
static void
|
||||
source_queue_relayout (ClutterActor *actor,
|
||||
ClutterAlignConstraint *align)
|
||||
{
|
||||
if (align->actor != NULL)
|
||||
_clutter_actor_queue_only_relayout (align->actor);
|
||||
}
|
||||
|
||||
static void
|
||||
source_destroyed (ClutterActor *actor,
|
||||
ClutterAlignConstraint *align)
|
||||
{
|
||||
align->source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *new_actor)
|
||||
{
|
||||
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (meta);
|
||||
ClutterActorMetaClass *parent;
|
||||
|
||||
if (new_actor != NULL &&
|
||||
align->source != NULL &&
|
||||
clutter_actor_contains (new_actor, align->source))
|
||||
{
|
||||
g_warning (G_STRLOC ": The source actor '%s' is contained "
|
||||
"by the actor '%s' associated to the constraint "
|
||||
"'%s'",
|
||||
_clutter_actor_get_debug_name (align->source),
|
||||
_clutter_actor_get_debug_name (new_actor),
|
||||
_clutter_actor_meta_get_debug_name (meta));
|
||||
return;
|
||||
}
|
||||
|
||||
/* store the pointer to the actor, for later use */
|
||||
align->actor = new_actor;
|
||||
|
||||
parent = CLUTTER_ACTOR_META_CLASS (clutter_align_constraint_parent_class);
|
||||
parent->set_actor (meta, new_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterActorBox *allocation)
|
||||
{
|
||||
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
|
||||
gfloat source_width, source_height;
|
||||
gfloat actor_width, actor_height;
|
||||
gfloat offset_x_start, offset_y_start;
|
||||
gfloat pivot_x, pivot_y;
|
||||
|
||||
if (align->source == NULL)
|
||||
return;
|
||||
|
||||
clutter_actor_box_get_size (allocation, &actor_width, &actor_height);
|
||||
|
||||
clutter_actor_get_size (align->source, &source_width, &source_height);
|
||||
|
||||
pivot_x = align->pivot.x == -1.f
|
||||
? align->factor
|
||||
: align->pivot.x;
|
||||
pivot_y = align->pivot.y == -1.f
|
||||
? align->factor
|
||||
: align->pivot.y;
|
||||
|
||||
offset_x_start = pivot_x * -actor_width;
|
||||
offset_y_start = pivot_y * -actor_height;
|
||||
|
||||
switch (align->align_axis)
|
||||
{
|
||||
case CLUTTER_ALIGN_X_AXIS:
|
||||
allocation->x1 += offset_x_start + (source_width * align->factor);
|
||||
allocation->x2 = allocation->x1 + actor_width;
|
||||
break;
|
||||
|
||||
case CLUTTER_ALIGN_Y_AXIS:
|
||||
allocation->y1 += offset_y_start + (source_height * align->factor);
|
||||
allocation->y2 = allocation->y1 + actor_height;
|
||||
break;
|
||||
|
||||
case CLUTTER_ALIGN_BOTH:
|
||||
allocation->x1 += offset_x_start + (source_width * align->factor);
|
||||
allocation->y1 += offset_y_start + (source_height * align->factor);
|
||||
allocation->x2 = allocation->x1 + actor_width;
|
||||
allocation->y2 = allocation->y1 + actor_height;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_actor_box_clamp_to_pixel (allocation);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject);
|
||||
|
||||
if (align->source != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (align->source,
|
||||
G_CALLBACK (source_destroyed),
|
||||
align);
|
||||
g_signal_handlers_disconnect_by_func (align->source,
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
align);
|
||||
align->source = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_align_constraint_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
clutter_align_constraint_set_source (align, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_AXIS:
|
||||
clutter_align_constraint_set_align_axis (align, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_PIVOT_POINT:
|
||||
clutter_align_constraint_set_pivot_point (align, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_FACTOR:
|
||||
clutter_align_constraint_set_factor (align, g_value_get_float (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, align->source);
|
||||
break;
|
||||
|
||||
case PROP_ALIGN_AXIS:
|
||||
g_value_set_enum (value, align->align_axis);
|
||||
break;
|
||||
|
||||
case PROP_PIVOT_POINT:
|
||||
{
|
||||
graphene_point_t point;
|
||||
|
||||
clutter_align_constraint_get_pivot_point (align, &point);
|
||||
|
||||
g_value_set_boxed (value, &point);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_FACTOR:
|
||||
g_value_set_float (value, align->factor);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass);
|
||||
|
||||
meta_class->set_actor = clutter_align_constraint_set_actor;
|
||||
|
||||
constraint_class->update_allocation = clutter_align_constraint_update_allocation;
|
||||
|
||||
/**
|
||||
* ClutterAlignConstraint:source:
|
||||
*
|
||||
* The #ClutterActor used as the source for the alignment.
|
||||
*
|
||||
* The #ClutterActor must not be a child or a grandchild of the actor
|
||||
* using the constraint.
|
||||
*/
|
||||
obj_props[PROP_SOURCE] =
|
||||
g_param_spec_object ("source", NULL, NULL,
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
/**
|
||||
* ClutterAlignConstraint:align-axis:
|
||||
*
|
||||
* The axis to be used to compute the alignment
|
||||
*/
|
||||
obj_props[PROP_ALIGN_AXIS] =
|
||||
g_param_spec_enum ("align-axis", NULL, NULL,
|
||||
CLUTTER_TYPE_ALIGN_AXIS,
|
||||
CLUTTER_ALIGN_X_AXIS,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
/**
|
||||
* ClutterAlignConstraint:pivot-point:
|
||||
*
|
||||
* The pivot point used by the constraint. The pivot point is the
|
||||
* point in the constraint actor around which the aligning is applied,
|
||||
* with (0, 0) being the top left corner of the actor and (1, 1) the
|
||||
* bottom right corner of the actor.
|
||||
*
|
||||
* For example, setting the pivot point to (0.5, 0.5) and using a factor
|
||||
* of 1 for both axes will align the actors horizontal and vertical
|
||||
* center point with the bottom right corner of the source actor.
|
||||
*
|
||||
* By default, the pivot point is set to (-1, -1), which means it's not
|
||||
* used and the constrained actor will be aligned to always stay inside
|
||||
* the source actor.
|
||||
*/
|
||||
obj_props[PROP_PIVOT_POINT] =
|
||||
g_param_spec_boxed ("pivot-point", NULL, NULL,
|
||||
GRAPHENE_TYPE_POINT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterAlignConstraint:factor:
|
||||
*
|
||||
* The alignment factor, as a normalized value between 0.0 and 1.0
|
||||
*
|
||||
* The factor depends on the #ClutterAlignConstraint:align-axis property:
|
||||
* with an align-axis value of %CLUTTER_ALIGN_X_AXIS, 0.0 means left and
|
||||
* 1.0 means right; with a value of %CLUTTER_ALIGN_Y_AXIS, 0.0 means top
|
||||
* and 1.0 means bottom.
|
||||
*/
|
||||
obj_props[PROP_FACTOR] =
|
||||
g_param_spec_float ("factor", NULL, NULL,
|
||||
0.0, 1.0,
|
||||
0.0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
gobject_class->dispose = clutter_align_constraint_dispose;
|
||||
gobject_class->set_property = clutter_align_constraint_set_property;
|
||||
gobject_class->get_property = clutter_align_constraint_get_property;
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_align_constraint_init (ClutterAlignConstraint *self)
|
||||
{
|
||||
self->actor = NULL;
|
||||
self->source = NULL;
|
||||
self->align_axis = CLUTTER_ALIGN_X_AXIS;
|
||||
self->pivot.x = -1.f;
|
||||
self->pivot.y = -1.f;
|
||||
self->factor = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_new:
|
||||
* @source: (allow-none): the #ClutterActor to use as the source of the
|
||||
* alignment, or %NULL
|
||||
* @axis: the axis to be used to compute the alignment
|
||||
* @factor: the alignment factor, between 0.0 and 1.0
|
||||
*
|
||||
* Creates a new constraint, aligning a #ClutterActor's position with
|
||||
* regards of the size of the actor to @source, with the given
|
||||
* alignment @factor
|
||||
*
|
||||
* Return value: the newly created #ClutterAlignConstraint
|
||||
*/
|
||||
ClutterConstraint *
|
||||
clutter_align_constraint_new (ClutterActor *source,
|
||||
ClutterAlignAxis axis,
|
||||
gfloat factor)
|
||||
{
|
||||
g_return_val_if_fail (source == NULL || CLUTTER_IS_ACTOR (source), NULL);
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_ALIGN_CONSTRAINT,
|
||||
"source", source,
|
||||
"align-axis", axis,
|
||||
"factor", factor,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_set_source:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
* @source: (allow-none): a #ClutterActor, or %NULL to unset the source
|
||||
*
|
||||
* Sets the source of the alignment constraint
|
||||
*/
|
||||
void
|
||||
clutter_align_constraint_set_source (ClutterAlignConstraint *align,
|
||||
ClutterActor *source)
|
||||
{
|
||||
ClutterActor *old_source, *actor;
|
||||
ClutterActorMeta *meta;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
|
||||
g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source));
|
||||
|
||||
if (align->source == source)
|
||||
return;
|
||||
|
||||
meta = CLUTTER_ACTOR_META (align);
|
||||
actor = clutter_actor_meta_get_actor (meta);
|
||||
if (actor != NULL && source != NULL)
|
||||
{
|
||||
if (clutter_actor_contains (actor, source))
|
||||
{
|
||||
g_warning (G_STRLOC ": The source actor '%s' is contained "
|
||||
"by the actor '%s' associated to the constraint "
|
||||
"'%s'",
|
||||
_clutter_actor_get_debug_name (source),
|
||||
_clutter_actor_get_debug_name (actor),
|
||||
_clutter_actor_meta_get_debug_name (meta));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
old_source = align->source;
|
||||
if (old_source != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_destroyed),
|
||||
align);
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
align);
|
||||
}
|
||||
|
||||
align->source = source;
|
||||
if (align->source != NULL)
|
||||
{
|
||||
g_signal_connect (align->source, "queue-relayout",
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
align);
|
||||
g_signal_connect (align->source, "destroy",
|
||||
G_CALLBACK (source_destroyed),
|
||||
align);
|
||||
|
||||
if (align->actor != NULL)
|
||||
clutter_actor_queue_relayout (align->actor);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_SOURCE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_get_source:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
*
|
||||
* Retrieves the source of the alignment
|
||||
*
|
||||
* Return value: (transfer none): the #ClutterActor used as the source
|
||||
* of the alignment
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_align_constraint_get_source (ClutterAlignConstraint *align)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), NULL);
|
||||
|
||||
return align->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_set_align_axis:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
* @axis: the axis to which the alignment refers to
|
||||
*
|
||||
* Sets the axis to which the alignment refers to
|
||||
*/
|
||||
void
|
||||
clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align,
|
||||
ClutterAlignAxis axis)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
|
||||
|
||||
if (align->align_axis == axis)
|
||||
return;
|
||||
|
||||
align->align_axis = axis;
|
||||
|
||||
if (align->actor != NULL)
|
||||
clutter_actor_queue_relayout (align->actor);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_ALIGN_AXIS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_get_align_axis:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
*
|
||||
* Retrieves the value set using [method@Clutter.AlignConstraint.set_align_axis]
|
||||
*
|
||||
* Return value: the alignment axis
|
||||
*/
|
||||
ClutterAlignAxis
|
||||
clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align),
|
||||
CLUTTER_ALIGN_X_AXIS);
|
||||
|
||||
return align->align_axis;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_set_pivot_point:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
* @pivot_point: A #GraphenePoint
|
||||
*
|
||||
* Sets the pivot point used by the constraint, the pivot point is the
|
||||
* point in the constraint actor around which the aligning is applied,
|
||||
* with (0, 0) being the top left corner of the actor and (1, 1) the
|
||||
* bottom right corner of the actor.
|
||||
*
|
||||
* If -1 is used, the pivot point is unset and the constrained actor
|
||||
* will be aligned to always stay inside the source actor.
|
||||
*/
|
||||
void
|
||||
clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
|
||||
const graphene_point_t *pivot_point)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
|
||||
g_return_if_fail (pivot_point != NULL);
|
||||
g_return_if_fail (pivot_point->x == -1.f ||
|
||||
(pivot_point->x >= 0.f && pivot_point->x <= 1.f));
|
||||
g_return_if_fail (pivot_point->y == -1.f ||
|
||||
(pivot_point->y >= 0.f && pivot_point->y <= 1.f));
|
||||
|
||||
if (graphene_point_equal (&align->pivot, pivot_point))
|
||||
return;
|
||||
|
||||
align->pivot = *pivot_point;
|
||||
|
||||
if (align->actor != NULL)
|
||||
clutter_actor_queue_relayout (align->actor);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_PIVOT_POINT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_get_pivot_point
|
||||
* @align: a #ClutterAlignConstraint
|
||||
* @pivot_point: (out caller-allocates): return location for a #GraphenePoint
|
||||
*
|
||||
* Gets the pivot point used by the constraint set with
|
||||
* [method@Clutter.AlignConstraint.set_pivot_point]. If no custom pivot
|
||||
* point is set, -1 is set.
|
||||
*/
|
||||
void
|
||||
clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
|
||||
graphene_point_t *pivot_point)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
|
||||
g_return_if_fail (pivot_point != NULL);
|
||||
|
||||
*pivot_point = align->pivot;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_set_factor:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
* @factor: the alignment factor, between 0.0 and 1.0
|
||||
*
|
||||
* Sets the alignment factor of the constraint
|
||||
*
|
||||
* The factor depends on the #ClutterAlignConstraint:align-axis property
|
||||
* and it is a value between 0.0 (meaning left, when
|
||||
* #ClutterAlignConstraint:align-axis is set to %CLUTTER_ALIGN_X_AXIS; or
|
||||
* meaning top, when #ClutterAlignConstraint:align-axis is set to
|
||||
* %CLUTTER_ALIGN_Y_AXIS) and 1.0 (meaning right, when
|
||||
* #ClutterAlignConstraint:align-axis is set to %CLUTTER_ALIGN_X_AXIS; or
|
||||
* meaning bottom, when #ClutterAlignConstraint:align-axis is set to
|
||||
* %CLUTTER_ALIGN_Y_AXIS). A value of 0.5 aligns in the middle in either
|
||||
* cases
|
||||
*/
|
||||
void
|
||||
clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
|
||||
gfloat factor)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
|
||||
|
||||
align->factor = CLAMP (factor, 0.0, 1.0);
|
||||
|
||||
if (align->actor != NULL)
|
||||
clutter_actor_queue_relayout (align->actor);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_FACTOR]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_align_constraint_get_factor:
|
||||
* @align: a #ClutterAlignConstraint
|
||||
*
|
||||
* Retrieves the factor set using [method@Clutter.AlignConstraint.set_factor]
|
||||
*
|
||||
* Return value: the alignment factor
|
||||
*/
|
||||
gfloat
|
||||
clutter_align_constraint_get_factor (ClutterAlignConstraint *align)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align), 0.0);
|
||||
|
||||
return align->factor;
|
||||
}
|
68
mutter/clutter/clutter/clutter-align-constraint.h
Normal file
68
mutter/clutter/clutter/clutter-align-constraint.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-constraint.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_ALIGN_CONSTRAINT (clutter_align_constraint_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ClutterAlignConstraint, clutter_align_constraint,
|
||||
CLUTTER, ALIGN_CONSTRAINT, ClutterConstraint)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterConstraint *clutter_align_constraint_new (ClutterActor *source,
|
||||
ClutterAlignAxis axis,
|
||||
gfloat factor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_align_constraint_set_source (ClutterAlignConstraint *align,
|
||||
ClutterActor *source);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_align_constraint_get_source (ClutterAlignConstraint *align);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align,
|
||||
ClutterAlignAxis axis);
|
||||
CLUTTER_EXPORT
|
||||
ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
|
||||
const graphene_point_t *pivot_point);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
|
||||
graphene_point_t *pivot_point);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
|
||||
gfloat factor);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_align_constraint_get_factor (ClutterAlignConstraint *align);
|
||||
|
||||
G_END_DECLS
|
207
mutter/clutter/clutter/clutter-animatable.c
Normal file
207
mutter/clutter/clutter/clutter-animatable.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterAnimatable:
|
||||
*
|
||||
* Interface for animatable classes
|
||||
*
|
||||
* #ClutterAnimatable is an interface that allows a [class@GObject.Object] class
|
||||
* to control how an actor will animate a property.
|
||||
*
|
||||
* Each #ClutterAnimatable should implement the
|
||||
* [vfunc@Animatable.interpolate_value] virtual function of the
|
||||
* interface to compute the animation state between two values of an interval
|
||||
* depending on a progress factor, expressed as a floating point value.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-animatable.h"
|
||||
#include "clutter/clutter-interval.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
clutter_animatable_default_init (ClutterAnimatableInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animatable_find_property:
|
||||
* @animatable: a #ClutterAnimatable
|
||||
* @property_name: the name of the animatable property to find
|
||||
*
|
||||
* Finds the [class@GObject.ParamSpec] for @property_name
|
||||
*
|
||||
* Return value: (transfer none): The #GParamSpec for the given property
|
||||
* or %NULL
|
||||
*/
|
||||
GParamSpec *
|
||||
clutter_animatable_find_property (ClutterAnimatable *animatable,
|
||||
const gchar *property_name)
|
||||
{
|
||||
ClutterAnimatableInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
|
||||
g_return_val_if_fail (property_name != NULL, NULL);
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Looking for property '%s'", property_name);
|
||||
|
||||
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
|
||||
if (iface->find_property != NULL)
|
||||
return iface->find_property (animatable, property_name);
|
||||
|
||||
return g_object_class_find_property (G_OBJECT_GET_CLASS (animatable),
|
||||
property_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animatable_get_initial_state:
|
||||
* @animatable: a #ClutterAnimatable
|
||||
* @property_name: the name of the animatable property to retrieve
|
||||
* @value: a #GValue initialized to the type of the property to retrieve
|
||||
*
|
||||
* Retrieves the current state of @property_name and sets @value with it
|
||||
*/
|
||||
void
|
||||
clutter_animatable_get_initial_state (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
GValue *value)
|
||||
{
|
||||
ClutterAnimatableInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
|
||||
g_return_if_fail (property_name != NULL);
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Getting initial state of '%s'", property_name);
|
||||
|
||||
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
|
||||
if (iface->get_initial_state != NULL)
|
||||
iface->get_initial_state (animatable, property_name, value);
|
||||
else
|
||||
g_object_get_property (G_OBJECT (animatable), property_name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animatable_set_final_state:
|
||||
* @animatable: a #ClutterAnimatable
|
||||
* @property_name: the name of the animatable property to set
|
||||
* @value: the value of the animatable property to set
|
||||
*
|
||||
* Sets the current state of @property_name to @value
|
||||
*/
|
||||
void
|
||||
clutter_animatable_set_final_state (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
const GValue *value)
|
||||
{
|
||||
ClutterAnimatableInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
|
||||
g_return_if_fail (property_name != NULL);
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Setting state of property '%s'", property_name);
|
||||
|
||||
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
|
||||
if (iface->set_final_state != NULL)
|
||||
iface->set_final_state (animatable, property_name, value);
|
||||
else
|
||||
g_object_set_property (G_OBJECT (animatable), property_name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animatable_interpolate_value:
|
||||
* @animatable: a #ClutterAnimatable
|
||||
* @property_name: the name of the property to interpolate
|
||||
* @interval: a #ClutterInterval with the animation range
|
||||
* @progress: the progress to use to interpolate between the
|
||||
* initial and final values of the @interval
|
||||
* @value: (out): return location for an initialized #GValue
|
||||
* using the same type of the @interval
|
||||
*
|
||||
* Asks a #ClutterAnimatable implementation to interpolate a
|
||||
* a named property between the initial and final values of
|
||||
* a #ClutterInterval, using @progress as the interpolation
|
||||
* value, and store the result inside @value.
|
||||
*
|
||||
* This function should be used for every property animation
|
||||
* involving `ClutterAnimatable`s.
|
||||
*
|
||||
* Return value: %TRUE if the interpolation was successful,
|
||||
* and %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
ClutterInterval *interval,
|
||||
gdouble progress,
|
||||
GValue *value)
|
||||
{
|
||||
ClutterAnimatableInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
|
||||
g_return_val_if_fail (property_name != NULL, FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INTERVAL (interval), FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Interpolating '%s' (progress: %.3f)",
|
||||
property_name,
|
||||
progress);
|
||||
|
||||
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
|
||||
if (iface->interpolate_value != NULL)
|
||||
{
|
||||
return iface->interpolate_value (animatable, property_name,
|
||||
interval,
|
||||
progress,
|
||||
value);
|
||||
}
|
||||
else
|
||||
return clutter_interval_compute_value (interval, progress, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animatable_get_actor:
|
||||
* @animatable: a #ClutterAnimatable
|
||||
*
|
||||
* Get animated actor.
|
||||
*
|
||||
* Return value: (transfer none): a #ClutterActor
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_animatable_get_actor (ClutterAnimatable *animatable)
|
||||
{
|
||||
ClutterAnimatableInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
|
||||
|
||||
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
|
||||
|
||||
g_return_val_if_fail (iface->get_actor, NULL);
|
||||
|
||||
return iface->get_actor (animatable);
|
||||
}
|
97
mutter/clutter/clutter/clutter-animatable.h
Normal file
97
mutter/clutter/clutter/clutter-animatable.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
|
||||
CLUTTER, ANIMATABLE,
|
||||
GObject)
|
||||
|
||||
/**
|
||||
* ClutterAnimatableInterface:
|
||||
* @find_property: virtual function for retrieving the #GParamSpec of
|
||||
* an animatable property
|
||||
* @get_initial_state: virtual function for retrieving the initial
|
||||
* state of an animatable property
|
||||
* @set_final_state: virtual function for setting the state of an
|
||||
* animatable property
|
||||
* @interpolate_value: virtual function for interpolating the progress
|
||||
* of a property
|
||||
* @get_actor: virtual function for getting associated actor
|
||||
*/
|
||||
struct _ClutterAnimatableInterface
|
||||
{
|
||||
/*< private >*/
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
/*< public >*/
|
||||
GParamSpec *(* find_property) (ClutterAnimatable *animatable,
|
||||
const gchar *property_name);
|
||||
void (* get_initial_state) (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
GValue *value);
|
||||
void (* set_final_state) (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
const GValue *value);
|
||||
gboolean (* interpolate_value) (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
ClutterInterval *interval,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GParamSpec *clutter_animatable_find_property (ClutterAnimatable *animatable,
|
||||
const gchar *property_name);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_animatable_get_initial_state (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
GValue *value);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_animatable_set_final_state (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
const GValue *value);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
|
||||
const gchar *property_name,
|
||||
ClutterInterval *interval,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_animatable_get_actor (ClutterAnimatable *animatable);
|
||||
|
||||
G_END_DECLS
|
107
mutter/clutter/clutter/clutter-backend-private.h
Normal file
107
mutter/clutter/clutter/clutter-backend-private.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-backend.h"
|
||||
#include "clutter/clutter-seat.h"
|
||||
#include "clutter/clutter-stage-window.h"
|
||||
|
||||
#define CLUTTER_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND, ClutterBackendClass))
|
||||
#define CLUTTER_IS_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND))
|
||||
#define CLUTTER_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND, ClutterBackendClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterBackendPrivate ClutterBackendPrivate;
|
||||
|
||||
struct _ClutterBackend
|
||||
{
|
||||
/*< private >*/
|
||||
GObject parent_instance;
|
||||
|
||||
CoglRenderer *cogl_renderer;
|
||||
CoglDisplay *cogl_display;
|
||||
CoglContext *cogl_context;
|
||||
GSource *cogl_source;
|
||||
|
||||
CoglOnscreen *dummy_onscreen;
|
||||
|
||||
cairo_font_options_t *font_options;
|
||||
|
||||
gchar *font_name;
|
||||
|
||||
float fallback_resource_scale;
|
||||
|
||||
ClutterStageWindow *stage_window;
|
||||
|
||||
ClutterInputMethod *input_method;
|
||||
};
|
||||
|
||||
struct _ClutterBackendClass
|
||||
{
|
||||
/*< private >*/
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* vfuncs */
|
||||
ClutterStageWindow * (* create_stage) (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error);
|
||||
CoglRenderer * (* get_renderer) (ClutterBackend *backend,
|
||||
GError **error);
|
||||
CoglDisplay * (* get_display) (ClutterBackend *backend,
|
||||
CoglRenderer *renderer,
|
||||
CoglSwapChain *swap_chain,
|
||||
GError **error);
|
||||
gboolean (* create_context) (ClutterBackend *backend,
|
||||
GError **error);
|
||||
|
||||
ClutterSeat * (* get_default_seat) (ClutterBackend *backend);
|
||||
|
||||
gboolean (* is_display_server) (ClutterBackend *backend);
|
||||
|
||||
/* signals */
|
||||
void (* resolution_changed) (ClutterBackend *backend);
|
||||
void (* font_changed) (ClutterBackend *backend);
|
||||
void (* settings_changed) (ClutterBackend *backend);
|
||||
};
|
||||
|
||||
ClutterStageWindow * _clutter_backend_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error);
|
||||
gboolean _clutter_backend_create_context (ClutterBackend *backend,
|
||||
GError **error);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterStageWindow * clutter_backend_get_stage_window (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
|
||||
float fallback_resource_scale);
|
||||
|
||||
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
|
603
mutter/clutter/clutter/clutter-backend.c
Normal file
603
mutter/clutter/clutter/clutter-backend.c
Normal file
@ -0,0 +1,603 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By:
|
||||
* Matthew Allum <mallum@openedhand.com>
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
|
||||
* Copyright (C) 2009, 2010 Intel Corp
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterBackend:
|
||||
*
|
||||
* Backend abstraction
|
||||
*
|
||||
* Clutter can be compiled against different backends. Each backend
|
||||
* has to implement a set of functions, in order to be used by Clutter.
|
||||
*
|
||||
* #ClutterBackend is the base class abstracting the various implementation;
|
||||
* it provides a basic API to query the backend for generic information
|
||||
* and settings.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-backend-private.h"
|
||||
#include "clutter/clutter-context-private.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-event-private.h"
|
||||
#include "clutter/clutter-marshal.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-stage-manager-private.h"
|
||||
#include "clutter/clutter-stage-private.h"
|
||||
#include "clutter/clutter-stage-window.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#define DEFAULT_FONT_NAME "Sans 10"
|
||||
|
||||
enum
|
||||
{
|
||||
RESOLUTION_CHANGED,
|
||||
FONT_CHANGED,
|
||||
SETTINGS_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT)
|
||||
|
||||
static guint backend_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void
|
||||
clutter_backend_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
||||
|
||||
/* clear the events still in the queue of the main context */
|
||||
_clutter_clear_events_queue ();
|
||||
|
||||
g_clear_object (&backend->dummy_onscreen);
|
||||
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_clear_object (&backend->input_method);
|
||||
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_real_resolution_changed (ClutterBackend *backend)
|
||||
{
|
||||
ClutterContext *context;
|
||||
ClutterSettings *settings;
|
||||
gdouble resolution;
|
||||
gint dpi;
|
||||
|
||||
settings = clutter_settings_get_default ();
|
||||
g_object_get (settings, "font-dpi", &dpi, NULL);
|
||||
|
||||
if (dpi < 0)
|
||||
resolution = 96.0;
|
||||
else
|
||||
resolution = dpi / 1024.0;
|
||||
|
||||
context = _clutter_context_get_default ();
|
||||
if (context->font_map != NULL)
|
||||
cogl_pango_font_map_set_resolution (context->font_map, resolution);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
CoglDriver driver_id,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
CoglSwapChain *swap_chain;
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
|
||||
swap_chain = NULL;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl renderer");
|
||||
backend->cogl_renderer = klass->get_renderer (backend, 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))
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl swap chain");
|
||||
swap_chain = cogl_swap_chain_new ();
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl display");
|
||||
if (klass->get_display != NULL)
|
||||
{
|
||||
backend->cogl_display = klass->get_display (backend,
|
||||
backend->cogl_renderer,
|
||||
swap_chain,
|
||||
error);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglOnscreenTemplate *tmpl;
|
||||
gboolean res;
|
||||
|
||||
tmpl = cogl_onscreen_template_new (swap_chain);
|
||||
|
||||
/* XXX: I have some doubts that this is a good design.
|
||||
*
|
||||
* Conceptually should we be able to check an onscreen_template
|
||||
* without more details about the CoglDisplay configuration?
|
||||
*/
|
||||
res = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
|
||||
tmpl,
|
||||
error);
|
||||
|
||||
if (!res)
|
||||
goto error;
|
||||
|
||||
backend->cogl_display = cogl_display_new (backend->cogl_renderer, tmpl);
|
||||
|
||||
/* the display owns the template */
|
||||
g_object_unref (tmpl);
|
||||
}
|
||||
|
||||
if (backend->cogl_display == NULL)
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Setting up the display");
|
||||
if (!cogl_display_setup (backend->cogl_display, error))
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating the Cogl context");
|
||||
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
|
||||
if (backend->cogl_context == NULL)
|
||||
goto error;
|
||||
|
||||
/* the display owns the renderer and the swap chain */
|
||||
g_object_unref (backend->cogl_renderer);
|
||||
g_object_unref (swap_chain);
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
g_clear_object (&backend->cogl_display);
|
||||
g_clear_object (&backend->cogl_renderer);
|
||||
|
||||
if (swap_chain != NULL)
|
||||
g_object_unref (swap_chain);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *driver_name;
|
||||
const char *driver_desc;
|
||||
CoglDriver driver_id;
|
||||
} all_known_drivers[] = {
|
||||
{ "gl3", "OpenGL 3.1 core profile", COGL_DRIVER_GL3 },
|
||||
{ "gles2", "OpenGL ES 2.0", COGL_DRIVER_GLES2 },
|
||||
{ "any", "Default Cogl driver", COGL_DRIVER_ANY },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
clutter_backend_real_create_context (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
GError *internal_error = NULL;
|
||||
const char *drivers_list;
|
||||
char **known_drivers;
|
||||
int i;
|
||||
|
||||
if (backend->cogl_context != NULL)
|
||||
return TRUE;
|
||||
|
||||
drivers_list = g_getenv ("CLUTTER_DRIVER");
|
||||
if (drivers_list == NULL)
|
||||
drivers_list = "*";
|
||||
|
||||
known_drivers = g_strsplit (drivers_list, ",", 0);
|
||||
|
||||
for (i = 0; backend->cogl_context == NULL && known_drivers[i] != NULL; i++)
|
||||
{
|
||||
const char *driver_name = known_drivers[i];
|
||||
gboolean is_any = g_str_equal (driver_name, "*");
|
||||
int j;
|
||||
|
||||
for (j = 0; j < G_N_ELEMENTS (all_known_drivers); j++)
|
||||
{
|
||||
if (is_any ||
|
||||
g_str_equal (all_known_drivers[j].driver_name, driver_name))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Checking for the %s driver", all_known_drivers[j].driver_desc);
|
||||
|
||||
if (clutter_backend_do_real_create_context (backend, all_known_drivers[j].driver_id, &internal_error))
|
||||
break;
|
||||
|
||||
if (internal_error)
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Unable to use the %s driver: %s",
|
||||
all_known_drivers[j].driver_desc,
|
||||
internal_error->message);
|
||||
g_clear_error (&internal_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (known_drivers);
|
||||
|
||||
if (backend->cogl_context == NULL)
|
||||
{
|
||||
if (internal_error != NULL)
|
||||
g_propagate_error (error, internal_error);
|
||||
else
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Unable to initialize the Clutter backend: no available drivers found.");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
backend->cogl_source = cogl_glib_source_new (backend->cogl_context, G_PRIORITY_DEFAULT);
|
||||
g_source_attach (backend->cogl_source, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_class_init (ClutterBackendClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_backend_dispose;
|
||||
|
||||
/**
|
||||
* ClutterBackend::resolution-changed:
|
||||
* @backend: the #ClutterBackend that emitted the signal
|
||||
*
|
||||
* The signal is emitted each time the font
|
||||
* resolutions has been changed through #ClutterSettings.
|
||||
*/
|
||||
backend_signals[RESOLUTION_CHANGED] =
|
||||
g_signal_new (I_("resolution-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (ClutterBackendClass, resolution_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* ClutterBackend::font-changed:
|
||||
* @backend: the #ClutterBackend that emitted the signal
|
||||
*
|
||||
* The signal is emitted each time the font options
|
||||
* have been changed through #ClutterSettings.
|
||||
*/
|
||||
backend_signals[FONT_CHANGED] =
|
||||
g_signal_new (I_("font-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (ClutterBackendClass, font_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* ClutterBackend::settings-changed:
|
||||
* @backend: the #ClutterBackend that emitted the signal
|
||||
*
|
||||
* The signal is emitted each time the #ClutterSettings
|
||||
* properties have been changed.
|
||||
*/
|
||||
backend_signals[SETTINGS_CHANGED] =
|
||||
g_signal_new (I_("settings-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (ClutterBackendClass, settings_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
klass->resolution_changed = clutter_backend_real_resolution_changed;
|
||||
|
||||
klass->create_context = clutter_backend_real_create_context;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_init (ClutterBackend *self)
|
||||
{
|
||||
self->dummy_onscreen = NULL;
|
||||
|
||||
self->fallback_resource_scale = 1.f;
|
||||
}
|
||||
|
||||
ClutterStageWindow *
|
||||
_clutter_backend_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
ClutterStageWindow *stage_window;
|
||||
|
||||
g_assert (CLUTTER_IS_BACKEND (backend));
|
||||
g_assert (CLUTTER_IS_STAGE (wrapper));
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (klass->create_stage != NULL)
|
||||
stage_window = klass->create_stage (backend, wrapper, error);
|
||||
else
|
||||
stage_window = NULL;
|
||||
|
||||
if (stage_window == NULL)
|
||||
return NULL;
|
||||
|
||||
g_assert (CLUTTER_IS_STAGE_WINDOW (stage_window));
|
||||
|
||||
backend->stage_window = stage_window;
|
||||
g_object_add_weak_pointer (G_OBJECT (backend->stage_window),
|
||||
(gpointer *) &backend->stage_window);
|
||||
|
||||
return stage_window;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_backend_create_context (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
|
||||
return klass->create_context (backend, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_get_default_backend:
|
||||
*
|
||||
* Retrieves the default #ClutterBackend used by Clutter. The
|
||||
* #ClutterBackend holds backend-specific configuration options.
|
||||
*
|
||||
* Return value: (transfer none): the default backend. You should
|
||||
* not ref or unref the returned object. Applications should rarely
|
||||
* need to use this.
|
||||
*/
|
||||
ClutterBackend *
|
||||
clutter_get_default_backend (void)
|
||||
{
|
||||
ClutterContext *clutter_context;
|
||||
|
||||
clutter_context = _clutter_context_get_default ();
|
||||
|
||||
return clutter_context->backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_get_resolution:
|
||||
* @backend: a #ClutterBackend
|
||||
*
|
||||
* Gets the resolution for font handling on the screen.
|
||||
*
|
||||
* The resolution is a scale factor between points specified in a
|
||||
* #PangoFontDescription and cairo units. The default value is 96.0,
|
||||
* meaning that a 10 point font will be 13 units
|
||||
* high (10 * 96. / 72. = 13.3).
|
||||
*
|
||||
* Clutter will set the resolution using the current backend when
|
||||
* initializing; the resolution is also stored in the
|
||||
* #ClutterSettings:font-dpi property.
|
||||
*
|
||||
* Return value: the current resolution, or -1 if no resolution
|
||||
* has been set.
|
||||
*/
|
||||
gdouble
|
||||
clutter_backend_get_resolution (ClutterBackend *backend)
|
||||
{
|
||||
ClutterSettings *settings;
|
||||
gint resolution;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), -1.0);
|
||||
|
||||
settings = clutter_settings_get_default ();
|
||||
g_object_get (settings, "font-dpi", &resolution, NULL);
|
||||
|
||||
if (resolution < 0)
|
||||
return 96.0;
|
||||
|
||||
return resolution / 1024.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_set_font_options:
|
||||
* @backend: a #ClutterBackend
|
||||
* @options: Cairo font options for the backend, or %NULL
|
||||
*
|
||||
* Sets the new font options for @backend. The #ClutterBackend will
|
||||
* copy the #cairo_font_options_t.
|
||||
*
|
||||
* If @options is %NULL, the first following call to
|
||||
* [method@Clutter.Backend.get_font_options] will return the default font
|
||||
* options for @backend.
|
||||
*
|
||||
* This function is intended for actors creating a Pango layout
|
||||
* using the PangoCairo API.
|
||||
*/
|
||||
void
|
||||
clutter_backend_set_font_options (ClutterBackend *backend,
|
||||
const cairo_font_options_t *options)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||
|
||||
if (backend->font_options != options)
|
||||
{
|
||||
if (backend->font_options)
|
||||
cairo_font_options_destroy (backend->font_options);
|
||||
|
||||
if (options)
|
||||
backend->font_options = cairo_font_options_copy (options);
|
||||
else
|
||||
backend->font_options = NULL;
|
||||
|
||||
g_signal_emit (backend, backend_signals[FONT_CHANGED], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_get_font_options:
|
||||
* @backend: a #ClutterBackend
|
||||
*
|
||||
* Retrieves the font options for @backend.
|
||||
*
|
||||
* Return value: (transfer none): the font options of the #ClutterBackend.
|
||||
* The returned #cairo_font_options_t is owned by the backend and should
|
||||
* not be modified or freed
|
||||
*/
|
||||
const cairo_font_options_t *
|
||||
clutter_backend_get_font_options (ClutterBackend *backend)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
|
||||
|
||||
if (G_LIKELY (backend->font_options))
|
||||
return backend->font_options;
|
||||
|
||||
backend->font_options = cairo_font_options_create ();
|
||||
|
||||
cairo_font_options_set_hint_style (backend->font_options, CAIRO_HINT_STYLE_NONE);
|
||||
cairo_font_options_set_subpixel_order (backend->font_options, CAIRO_SUBPIXEL_ORDER_DEFAULT);
|
||||
cairo_font_options_set_antialias (backend->font_options, CAIRO_ANTIALIAS_DEFAULT);
|
||||
|
||||
g_signal_emit (backend, backend_signals[FONT_CHANGED], 0);
|
||||
|
||||
return backend->font_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_get_cogl_context:
|
||||
* @backend: a #ClutterBackend
|
||||
*
|
||||
* Retrieves the #CoglContext associated with the given clutter
|
||||
* @backend. A #CoglContext is required when using some of the
|
||||
* experimental 2.0 Cogl API.
|
||||
*
|
||||
* Since CoglContext is itself experimental API this API should
|
||||
* be considered experimental too.
|
||||
*
|
||||
* This API is not yet supported on OSX because OSX still
|
||||
* uses the stub Cogl winsys and the Clutter backend doesn't
|
||||
* explicitly create a CoglContext.
|
||||
*
|
||||
* Return value: (transfer none): The #CoglContext associated with @backend.
|
||||
*/
|
||||
CoglContext *
|
||||
clutter_backend_get_cogl_context (ClutterBackend *backend)
|
||||
{
|
||||
return backend->cogl_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_get_input_method:
|
||||
* @backend: the #CLutterBackend
|
||||
*
|
||||
* Returns the input method used by Clutter
|
||||
*
|
||||
* Returns: (transfer none): the input method
|
||||
**/
|
||||
ClutterInputMethod *
|
||||
clutter_backend_get_input_method (ClutterBackend *backend)
|
||||
{
|
||||
return backend->input_method;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_set_input_method:
|
||||
* @backend: the #ClutterBackend
|
||||
* @method: (nullable): the input method
|
||||
*
|
||||
* Sets the input method to be used by Clutter
|
||||
**/
|
||||
void
|
||||
clutter_backend_set_input_method (ClutterBackend *backend,
|
||||
ClutterInputMethod *method)
|
||||
{
|
||||
if (backend->input_method == method)
|
||||
return;
|
||||
|
||||
if (backend->input_method)
|
||||
clutter_input_method_focus_out (backend->input_method);
|
||||
|
||||
g_set_object (&backend->input_method, method);
|
||||
}
|
||||
|
||||
ClutterStageWindow *
|
||||
clutter_backend_get_stage_window (ClutterBackend *backend)
|
||||
{
|
||||
return backend->stage_window;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_backend_get_default_seat:
|
||||
* @backend: the #ClutterBackend
|
||||
*
|
||||
* Returns the default seat
|
||||
*
|
||||
* Returns: (transfer none): the default seat
|
||||
**/
|
||||
ClutterSeat *
|
||||
clutter_backend_get_default_seat (ClutterBackend *backend)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
|
||||
|
||||
return CLUTTER_BACKEND_GET_CLASS (backend)->get_default_seat (backend);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
|
||||
float fallback_resource_scale)
|
||||
{
|
||||
backend->fallback_resource_scale = fallback_resource_scale;
|
||||
}
|
||||
|
||||
float
|
||||
clutter_backend_get_fallback_resource_scale (ClutterBackend *backend)
|
||||
{
|
||||
return backend->fallback_resource_scale;
|
||||
}
|
||||
|
||||
gboolean
|
||||
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);
|
||||
}
|
76
mutter/clutter/clutter/clutter-backend.h
Normal file
76
mutter/clutter/clutter/clutter-backend.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <cairo.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-keymap.h"
|
||||
#include "clutter/clutter-types.h"
|
||||
#include "clutter/clutter-seat.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BACKEND (clutter_backend_get_type ())
|
||||
#define CLUTTER_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND, ClutterBackend))
|
||||
#define CLUTTER_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND))
|
||||
|
||||
typedef struct _ClutterBackend ClutterBackend;
|
||||
typedef struct _ClutterBackendClass ClutterBackendClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_backend_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterBackend * clutter_get_default_backend (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gdouble clutter_backend_get_resolution (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_backend_set_font_options (ClutterBackend *backend,
|
||||
const cairo_font_options_t *options);
|
||||
CLUTTER_EXPORT
|
||||
const cairo_font_options_t * clutter_backend_get_font_options (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
CoglContext * clutter_backend_get_cogl_context (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputMethod * clutter_backend_get_input_method (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_backend_set_input_method (ClutterBackend *backend,
|
||||
ClutterInputMethod *method);
|
||||
CLUTTER_EXPORT
|
||||
ClutterSeat * clutter_backend_get_default_seat (ClutterBackend *backend);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
85
mutter/clutter/clutter/clutter-base-types.c
Normal file
85
mutter/clutter/clutter/clutter-base-types.c
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define FLOAT_EPSILON (1e-15)
|
||||
|
||||
/*
|
||||
* ClutterMargin
|
||||
*/
|
||||
|
||||
/**
|
||||
* clutter_margin_new:
|
||||
*
|
||||
* Creates a new #ClutterMargin.
|
||||
*
|
||||
* Return value: (transfer full): a newly allocated #ClutterMargin. Use
|
||||
* [method@Clutter.Margin.free] to free the resources associated with it when
|
||||
* done.
|
||||
*/
|
||||
ClutterMargin *
|
||||
clutter_margin_new (void)
|
||||
{
|
||||
return g_new0 (ClutterMargin, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_margin_copy:
|
||||
* @margin_: a #ClutterMargin
|
||||
*
|
||||
* Creates a new #ClutterMargin and copies the contents of @margin_ into
|
||||
* the newly created structure.
|
||||
*
|
||||
* Return value: (transfer full): a copy of the #ClutterMargin.
|
||||
*/
|
||||
ClutterMargin *
|
||||
clutter_margin_copy (const ClutterMargin *margin_)
|
||||
{
|
||||
if (G_LIKELY (margin_ != NULL))
|
||||
return g_memdup2 (margin_, sizeof (ClutterMargin));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_margin_free:
|
||||
* @margin_: a #ClutterMargin
|
||||
*
|
||||
* Frees the resources allocated by [ctor@Clutter.Margin.new] and
|
||||
* [method@Clutter.Margin.copy].
|
||||
*/
|
||||
void
|
||||
clutter_margin_free (ClutterMargin *margin_)
|
||||
{
|
||||
if (G_LIKELY (margin_ != NULL))
|
||||
g_free (margin_);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterMargin, clutter_margin,
|
||||
clutter_margin_copy,
|
||||
clutter_margin_free)
|
279
mutter/clutter/clutter/clutter-bin-layout.c
Normal file
279
mutter/clutter/clutter/clutter-bin-layout.c
Normal file
@ -0,0 +1,279 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterBinLayout:
|
||||
*
|
||||
* A simple layout manager
|
||||
*
|
||||
* #ClutterBinLayout is a layout manager which implements the following
|
||||
* policy:
|
||||
*
|
||||
* - the preferred size is the maximum preferred size
|
||||
* between all the children of the container using the
|
||||
* layout;
|
||||
* - each child is allocated in "layers", on on top
|
||||
* of the other;
|
||||
* - for each layer there are horizontal and vertical
|
||||
* alignment policies.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#include "clutter/clutter-animatable.h"
|
||||
#include "clutter/clutter-bin-layout.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-layout-meta.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterBinLayout,
|
||||
clutter_bin_layout,
|
||||
CLUTTER_TYPE_LAYOUT_MANAGER)
|
||||
|
||||
static void
|
||||
clutter_bin_layout_get_preferred_width (ClutterLayoutManager *manager,
|
||||
ClutterActor *container,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (container);
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
gfloat min_width, nat_width;
|
||||
|
||||
min_width = nat_width = 0.0;
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
gfloat minimum, natural;
|
||||
|
||||
if (!clutter_actor_is_visible (child))
|
||||
continue;
|
||||
|
||||
clutter_actor_get_preferred_width (child, for_height,
|
||||
&minimum,
|
||||
&natural);
|
||||
|
||||
min_width = MAX (min_width, minimum);
|
||||
nat_width = MAX (nat_width, natural);
|
||||
}
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = min_width;
|
||||
|
||||
if (nat_width_p)
|
||||
*nat_width_p = nat_width;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager,
|
||||
ClutterActor *container,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (container);
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
gfloat min_height, nat_height;
|
||||
|
||||
min_height = nat_height = 0.0;
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
gfloat minimum, natural;
|
||||
|
||||
if (!clutter_actor_is_visible (child))
|
||||
continue;
|
||||
|
||||
clutter_actor_get_preferred_height (child, for_width,
|
||||
&minimum,
|
||||
&natural);
|
||||
|
||||
min_height = MAX (min_height, minimum);
|
||||
nat_height = MAX (nat_height, natural);
|
||||
}
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = min_height;
|
||||
|
||||
if (nat_height_p)
|
||||
*nat_height_p = nat_height;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
get_actor_align_factor (ClutterActorAlign alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case CLUTTER_ACTOR_ALIGN_CENTER:
|
||||
return 0.5;
|
||||
|
||||
case CLUTTER_ACTOR_ALIGN_START:
|
||||
return 0.0;
|
||||
|
||||
case CLUTTER_ACTOR_ALIGN_END:
|
||||
return 1.0;
|
||||
|
||||
case CLUTTER_ACTOR_ALIGN_FILL:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_allocate (ClutterLayoutManager *manager,
|
||||
ClutterActor *container,
|
||||
const ClutterActorBox *allocation)
|
||||
{
|
||||
gfloat allocation_x, allocation_y;
|
||||
gfloat available_w, available_h;
|
||||
ClutterActor *actor, *child;
|
||||
ClutterActorIter iter;
|
||||
|
||||
clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y);
|
||||
clutter_actor_box_get_size (allocation, &available_w, &available_h);
|
||||
|
||||
actor = CLUTTER_ACTOR (container);
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
ClutterActorBox child_alloc = { 0, };
|
||||
gdouble x_align, y_align;
|
||||
gboolean x_fill, y_fill, is_fixed_position_set;
|
||||
float fixed_x, fixed_y;
|
||||
|
||||
if (!clutter_actor_is_visible (child))
|
||||
continue;
|
||||
|
||||
fixed_x = fixed_y = 0.f;
|
||||
g_object_get (child,
|
||||
"fixed-position-set", &is_fixed_position_set,
|
||||
"fixed-x", &fixed_x,
|
||||
"fixed-y", &fixed_y,
|
||||
NULL);
|
||||
|
||||
if (is_fixed_position_set)
|
||||
{
|
||||
if (is_fixed_position_set)
|
||||
child_alloc.x1 = fixed_x;
|
||||
else
|
||||
child_alloc.x1 = clutter_actor_get_x (child);
|
||||
}
|
||||
else
|
||||
child_alloc.x1 = allocation_x;
|
||||
|
||||
if (is_fixed_position_set)
|
||||
{
|
||||
if (is_fixed_position_set)
|
||||
child_alloc.y1 = fixed_y;
|
||||
else
|
||||
child_alloc.y1 = clutter_actor_get_y (child);
|
||||
}
|
||||
else
|
||||
child_alloc.y1 = allocation_y;
|
||||
|
||||
child_alloc.x2 = allocation_x + available_w;
|
||||
child_alloc.y2 = allocation_y + available_h;
|
||||
|
||||
if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL))
|
||||
{
|
||||
ClutterActorAlign align;
|
||||
|
||||
align = clutter_actor_get_x_align (child);
|
||||
x_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
|
||||
x_align = get_actor_align_factor (align);
|
||||
}
|
||||
else
|
||||
{
|
||||
x_fill = FALSE;
|
||||
|
||||
if (!is_fixed_position_set)
|
||||
x_align = 0.5;
|
||||
else
|
||||
x_align = 0.0;
|
||||
}
|
||||
|
||||
if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL))
|
||||
{
|
||||
ClutterActorAlign align;
|
||||
|
||||
align = clutter_actor_get_y_align (child);
|
||||
y_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
|
||||
y_align = get_actor_align_factor (align);
|
||||
}
|
||||
else
|
||||
{
|
||||
y_fill = FALSE;
|
||||
|
||||
if (!is_fixed_position_set)
|
||||
y_align = 0.5;
|
||||
else
|
||||
y_align = 0.0;
|
||||
}
|
||||
|
||||
clutter_actor_allocate_align_fill (child, &child_alloc,
|
||||
x_align, y_align,
|
||||
x_fill, y_fill);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_class_init (ClutterBinLayoutClass *klass)
|
||||
{
|
||||
ClutterLayoutManagerClass *layout_class =
|
||||
CLUTTER_LAYOUT_MANAGER_CLASS (klass);
|
||||
|
||||
layout_class->get_preferred_width = clutter_bin_layout_get_preferred_width;
|
||||
layout_class->get_preferred_height = clutter_bin_layout_get_preferred_height;
|
||||
layout_class->allocate = clutter_bin_layout_allocate;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_init (ClutterBinLayout *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bin_layout_new:
|
||||
*
|
||||
* Creates a new #ClutterBinLayout layout manager
|
||||
*
|
||||
* Return value: the newly created layout manager
|
||||
*/
|
||||
ClutterLayoutManager *
|
||||
clutter_bin_layout_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_BIN_LAYOUT,
|
||||
NULL);
|
||||
}
|
59
mutter/clutter/clutter/clutter-bin-layout.h
Normal file
59
mutter/clutter/clutter/clutter-bin-layout.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-layout-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BIN_LAYOUT (clutter_bin_layout_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterBinLayout,
|
||||
clutter_bin_layout,
|
||||
CLUTTER,
|
||||
BIN_LAYOUT,
|
||||
ClutterLayoutManager)
|
||||
|
||||
/**
|
||||
* ClutterBinLayoutClass:
|
||||
*
|
||||
* The #ClutterBinLayoutClass structure contains only private
|
||||
* data and should be accessed using the provided API
|
||||
*/
|
||||
struct _ClutterBinLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManagerClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterLayoutManager * clutter_bin_layout_new (void);
|
||||
|
||||
G_END_DECLS
|
617
mutter/clutter/clutter/clutter-bind-constraint.c
Normal file
617
mutter/clutter/clutter/clutter-bind-constraint.c
Normal file
@ -0,0 +1,617 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterBindConstraint:
|
||||
*
|
||||
* A constraint binding the position or size of an actor
|
||||
*
|
||||
* #ClutterBindConstraint is a [class@Constraint] that binds the
|
||||
* position or the size of the [class@Actor] to which it is applied
|
||||
* to the the position or the size of another [class@Actor], or
|
||||
* "source".
|
||||
*
|
||||
* An offset can be applied to the constraint, to avoid overlapping. The offset
|
||||
* can also be animated. For instance, the following code will set up three
|
||||
* actors to be bound to the same origin:
|
||||
*
|
||||
* ```c
|
||||
* // source
|
||||
* rect[0] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[0], &red_color);
|
||||
* clutter_actor_set_position (rect[0], x_pos, y_pos);
|
||||
* clutter_actor_set_size (rect[0], 100, 100);
|
||||
*
|
||||
* // second rectangle
|
||||
* rect[1] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[1], &green_color);
|
||||
* clutter_actor_set_size (rect[1], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[1], 0);
|
||||
*
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_X, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[1], "green-x", constraint);
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_Y, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
|
||||
*
|
||||
* // third rectangle
|
||||
* rect[2] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[2], &blue_color);
|
||||
* clutter_actor_set_size (rect[2], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[2], 0);
|
||||
*
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_X, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[2], "blue-x", constraint);
|
||||
* constraint = clutter_bind_constraint_new (rect[0], CLUTTER_BIND_Y, 0.0);
|
||||
* clutter_actor_add_constraint_with_name (rect[2], "blue-y", constraint);
|
||||
* ```
|
||||
*
|
||||
* The following code animates the second and third rectangles to "expand"
|
||||
* them horizontally from underneath the first rectangle:
|
||||
*
|
||||
* ```c
|
||||
* clutter_actor_animate (rect[1], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
* "@constraints.green-x.offset", 100.0,
|
||||
* "opacity", 255,
|
||||
* NULL);
|
||||
* clutter_actor_animate (rect[2], CLUTTER_EASE_OUT_CUBIC, 250,
|
||||
* "@constraints.blue-x.offset", 200.0,
|
||||
* "opacity", 255,
|
||||
* NULL);
|
||||
* ```
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter/clutter-bind-constraint.h"
|
||||
|
||||
#include "clutter/clutter-actor-meta-private.h"
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#include "clutter/clutter-constraint.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
struct _ClutterBindConstraint
|
||||
{
|
||||
ClutterConstraint parent_instance;
|
||||
|
||||
ClutterActor *actor;
|
||||
ClutterActor *source;
|
||||
ClutterBindCoordinate coordinate;
|
||||
gfloat offset;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_SOURCE,
|
||||
PROP_COORDINATE,
|
||||
PROP_OFFSET,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_FINAL_TYPE (ClutterBindConstraint,
|
||||
clutter_bind_constraint,
|
||||
CLUTTER_TYPE_CONSTRAINT);
|
||||
|
||||
static void
|
||||
source_queue_relayout (ClutterActor *source,
|
||||
ClutterBindConstraint *bind)
|
||||
{
|
||||
if (bind->actor != NULL)
|
||||
_clutter_actor_queue_only_relayout (bind->actor);
|
||||
}
|
||||
|
||||
static void
|
||||
source_destroyed (ClutterActor *actor,
|
||||
ClutterBindConstraint *bind)
|
||||
{
|
||||
bind->source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_update_preferred_size (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterOrientation direction,
|
||||
float for_size,
|
||||
float *minimum_size,
|
||||
float *natural_size)
|
||||
{
|
||||
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
|
||||
float source_min, source_nat;
|
||||
|
||||
if (bind->source == NULL)
|
||||
return;
|
||||
|
||||
/* only these bindings affect the preferred size */
|
||||
if (!(bind->coordinate == CLUTTER_BIND_WIDTH ||
|
||||
bind->coordinate == CLUTTER_BIND_HEIGHT ||
|
||||
bind->coordinate == CLUTTER_BIND_SIZE ||
|
||||
bind->coordinate == CLUTTER_BIND_ALL))
|
||||
return;
|
||||
|
||||
if (clutter_actor_contains (bind->source, actor))
|
||||
return;
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case CLUTTER_ORIENTATION_HORIZONTAL:
|
||||
if (bind->coordinate != CLUTTER_BIND_HEIGHT)
|
||||
{
|
||||
clutter_actor_get_preferred_width (bind->source, for_size,
|
||||
&source_min,
|
||||
&source_nat);
|
||||
|
||||
*minimum_size = source_min;
|
||||
*natural_size = source_nat;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLUTTER_ORIENTATION_VERTICAL:
|
||||
if (bind->coordinate != CLUTTER_BIND_WIDTH)
|
||||
{
|
||||
clutter_actor_get_preferred_height (bind->source, for_size,
|
||||
&source_min,
|
||||
&source_nat);
|
||||
|
||||
*minimum_size = source_min;
|
||||
*natural_size = source_nat;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_update_allocation (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterActorBox *allocation)
|
||||
{
|
||||
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
|
||||
gfloat source_width, source_height;
|
||||
gfloat actor_width, actor_height;
|
||||
graphene_point3d_t source_position;
|
||||
|
||||
source_position = GRAPHENE_POINT3D_INIT (0.f, 0.f, 0.f);
|
||||
|
||||
if (bind->source == NULL)
|
||||
return;
|
||||
|
||||
source_position.x = clutter_actor_get_x (bind->source);
|
||||
source_position.y = clutter_actor_get_y (bind->source);
|
||||
clutter_actor_get_size (bind->source, &source_width, &source_height);
|
||||
|
||||
clutter_actor_box_get_size (allocation, &actor_width, &actor_height);
|
||||
|
||||
switch (bind->coordinate)
|
||||
{
|
||||
case CLUTTER_BIND_X:
|
||||
allocation->x1 = source_position.x + bind->offset;
|
||||
allocation->x2 = allocation->x1 + actor_width;
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_Y:
|
||||
allocation->y1 = source_position.y + bind->offset;
|
||||
allocation->y2 = allocation->y1 + actor_height;
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_POSITION:
|
||||
allocation->x1 = source_position.x + bind->offset;
|
||||
allocation->y1 = source_position.y + bind->offset;
|
||||
allocation->x2 = allocation->x1 + actor_width;
|
||||
allocation->y2 = allocation->y1 + actor_height;
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_WIDTH:
|
||||
allocation->x2 = allocation->x1 + source_width + bind->offset;
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_HEIGHT:
|
||||
allocation->y2 = allocation->y1 + source_height + bind->offset;
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_SIZE:
|
||||
allocation->x2 = allocation->x1 + source_width + bind->offset;
|
||||
allocation->y2 = allocation->y1 + source_height + bind->offset;
|
||||
break;
|
||||
|
||||
case CLUTTER_BIND_ALL:
|
||||
allocation->x1 = source_position.x + bind->offset;
|
||||
allocation->y1 = source_position.y + bind->offset;
|
||||
allocation->x2 = allocation->x1 + source_width + bind->offset;
|
||||
allocation->y2 = allocation->y1 + source_height + bind->offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_actor_box_clamp_to_pixel (allocation);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *new_actor)
|
||||
{
|
||||
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (meta);
|
||||
ClutterActorMetaClass *parent;
|
||||
|
||||
if (new_actor != NULL &&
|
||||
bind->source != NULL &&
|
||||
clutter_actor_contains (new_actor, bind->source))
|
||||
{
|
||||
g_warning (G_STRLOC ": The source actor '%s' is contained "
|
||||
"by the actor '%s' associated to the constraint "
|
||||
"'%s'",
|
||||
_clutter_actor_get_debug_name (bind->source),
|
||||
_clutter_actor_get_debug_name (new_actor),
|
||||
_clutter_actor_meta_get_debug_name (meta));
|
||||
return;
|
||||
}
|
||||
|
||||
/* store the pointer to the actor, for later use */
|
||||
bind->actor = new_actor;
|
||||
|
||||
parent = CLUTTER_ACTOR_META_CLASS (clutter_bind_constraint_parent_class);
|
||||
parent->set_actor (meta, new_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject);
|
||||
|
||||
if (bind->source != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (bind->source,
|
||||
G_CALLBACK (source_destroyed),
|
||||
bind);
|
||||
g_signal_handlers_disconnect_by_func (bind->source,
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
bind);
|
||||
bind->source = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_bind_constraint_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
clutter_bind_constraint_set_source (bind, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_COORDINATE:
|
||||
clutter_bind_constraint_set_coordinate (bind, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_OFFSET:
|
||||
clutter_bind_constraint_set_offset (bind, g_value_get_float (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, bind->source);
|
||||
break;
|
||||
|
||||
case PROP_COORDINATE:
|
||||
g_value_set_enum (value, bind->coordinate);
|
||||
break;
|
||||
|
||||
case PROP_OFFSET:
|
||||
g_value_set_float (value, bind->offset);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass)
|
||||
{
|
||||
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
ClutterConstraintClass *constraint_class = CLUTTER_CONSTRAINT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = clutter_bind_constraint_set_property;
|
||||
gobject_class->get_property = clutter_bind_constraint_get_property;
|
||||
gobject_class->dispose = clutter_bind_constraint_dispose;
|
||||
|
||||
meta_class->set_actor = clutter_bind_constraint_set_actor;
|
||||
|
||||
constraint_class->update_allocation = clutter_bind_constraint_update_allocation;
|
||||
constraint_class->update_preferred_size = clutter_bind_constraint_update_preferred_size;
|
||||
|
||||
/**
|
||||
* ClutterBindConstraint:source:
|
||||
*
|
||||
* The #ClutterActor used as the source for the binding.
|
||||
*
|
||||
* The #ClutterActor must not be contained inside the actor associated
|
||||
* to the constraint.
|
||||
*/
|
||||
obj_props[PROP_SOURCE] =
|
||||
g_param_spec_object ("source", NULL, NULL,
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
/**
|
||||
* ClutterBindConstraint:coordinate:
|
||||
*
|
||||
* The coordinate to be bound
|
||||
*/
|
||||
obj_props[PROP_COORDINATE] =
|
||||
g_param_spec_enum ("coordinate", NULL, NULL,
|
||||
CLUTTER_TYPE_BIND_COORDINATE,
|
||||
CLUTTER_BIND_X,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
/**
|
||||
* ClutterBindConstraint:offset:
|
||||
*
|
||||
* The offset, in pixels, to be applied to the binding
|
||||
*/
|
||||
obj_props[PROP_OFFSET] =
|
||||
g_param_spec_float ("offset", NULL, NULL,
|
||||
-G_MAXFLOAT, G_MAXFLOAT,
|
||||
0.0f,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT);
|
||||
|
||||
g_object_class_install_properties (gobject_class,
|
||||
PROP_LAST,
|
||||
obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bind_constraint_init (ClutterBindConstraint *self)
|
||||
{
|
||||
self->actor = NULL;
|
||||
self->source = NULL;
|
||||
self->coordinate = CLUTTER_BIND_X;
|
||||
self->offset = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_new:
|
||||
* @source: (allow-none): the #ClutterActor to use as the source of
|
||||
* the binding, or %NULL
|
||||
* @coordinate: the coordinate to bind
|
||||
* @offset: the offset to apply to the binding, in pixels
|
||||
*
|
||||
* Creates a new constraint, binding a #ClutterActor's position to
|
||||
* the given @coordinate of the position of @source
|
||||
*
|
||||
* Return value: the newly created #ClutterBindConstraint
|
||||
*/
|
||||
ClutterConstraint *
|
||||
clutter_bind_constraint_new (ClutterActor *source,
|
||||
ClutterBindCoordinate coordinate,
|
||||
gfloat offset)
|
||||
{
|
||||
g_return_val_if_fail (source == NULL || CLUTTER_IS_ACTOR (source), NULL);
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_BIND_CONSTRAINT,
|
||||
"source", source,
|
||||
"coordinate", coordinate,
|
||||
"offset", offset,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_set_source:
|
||||
* @constraint: a #ClutterBindConstraint
|
||||
* @source: (allow-none): a #ClutterActor, or %NULL to unset the source
|
||||
*
|
||||
* Sets the source #ClutterActor for the constraint
|
||||
*/
|
||||
void
|
||||
clutter_bind_constraint_set_source (ClutterBindConstraint *constraint,
|
||||
ClutterActor *source)
|
||||
{
|
||||
ClutterActor *old_source, *actor;
|
||||
ClutterActorMeta *meta;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint));
|
||||
g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source));
|
||||
|
||||
if (constraint->source == source)
|
||||
return;
|
||||
|
||||
meta = CLUTTER_ACTOR_META (constraint);
|
||||
actor = clutter_actor_meta_get_actor (meta);
|
||||
if (source != NULL && actor != NULL)
|
||||
{
|
||||
if (clutter_actor_contains (actor, source))
|
||||
{
|
||||
g_warning (G_STRLOC ": The source actor '%s' is contained "
|
||||
"by the actor '%s' associated to the constraint "
|
||||
"'%s'",
|
||||
_clutter_actor_get_debug_name (source),
|
||||
_clutter_actor_get_debug_name (actor),
|
||||
_clutter_actor_meta_get_debug_name (meta));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
old_source = constraint->source;
|
||||
if (old_source != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_destroyed),
|
||||
constraint);
|
||||
g_signal_handlers_disconnect_by_func (old_source,
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
constraint);
|
||||
}
|
||||
|
||||
constraint->source = source;
|
||||
if (constraint->source != NULL)
|
||||
{
|
||||
g_signal_connect (constraint->source, "queue-relayout",
|
||||
G_CALLBACK (source_queue_relayout),
|
||||
constraint);
|
||||
g_signal_connect (constraint->source, "destroy",
|
||||
G_CALLBACK (source_destroyed),
|
||||
constraint);
|
||||
|
||||
if (constraint->actor != NULL)
|
||||
clutter_actor_queue_relayout (constraint->actor);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_SOURCE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_get_source:
|
||||
* @constraint: a #ClutterBindConstraint
|
||||
*
|
||||
* Retrieves the #ClutterActor set using [method@Clutter.BindConstraint.set_source]
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the source actor
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_bind_constraint_get_source (ClutterBindConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint), NULL);
|
||||
|
||||
return constraint->source;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_set_coordinate:
|
||||
* @constraint: a #ClutterBindConstraint
|
||||
* @coordinate: the coordinate to bind
|
||||
*
|
||||
* Sets the coordinate to bind in the constraint
|
||||
*/
|
||||
void
|
||||
clutter_bind_constraint_set_coordinate (ClutterBindConstraint *constraint,
|
||||
ClutterBindCoordinate coordinate)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint));
|
||||
|
||||
if (constraint->coordinate == coordinate)
|
||||
return;
|
||||
|
||||
constraint->coordinate = coordinate;
|
||||
|
||||
if (constraint->actor != NULL)
|
||||
clutter_actor_queue_relayout (constraint->actor);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_COORDINATE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_get_coordinate:
|
||||
* @constraint: a #ClutterBindConstraint
|
||||
*
|
||||
* Retrieves the bound coordinate of the constraint
|
||||
*
|
||||
* Return value: the bound coordinate
|
||||
*/
|
||||
ClutterBindCoordinate
|
||||
clutter_bind_constraint_get_coordinate (ClutterBindConstraint *constraint)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint),
|
||||
CLUTTER_BIND_X);
|
||||
|
||||
return constraint->coordinate;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_set_offset:
|
||||
* @constraint: a #ClutterBindConstraint
|
||||
* @offset: the offset to apply, in pixels
|
||||
*
|
||||
* Sets the offset to be applied to the constraint
|
||||
*/
|
||||
void
|
||||
clutter_bind_constraint_set_offset (ClutterBindConstraint *constraint,
|
||||
gfloat offset)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BIND_CONSTRAINT (constraint));
|
||||
|
||||
if (fabs (constraint->offset - offset) < 0.00001f)
|
||||
return;
|
||||
|
||||
constraint->offset = offset;
|
||||
|
||||
if (constraint->actor != NULL)
|
||||
clutter_actor_queue_relayout (constraint->actor);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (constraint), obj_props[PROP_OFFSET]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bind_constraint_get_offset:
|
||||
* @constraint: a #ClutterBindConstraint
|
||||
*
|
||||
* Retrieves the offset set using [method@Clutter.BindConstraint.set_offset]
|
||||
*
|
||||
* Return value: the offset, in pixels
|
||||
*/
|
||||
gfloat
|
||||
clutter_bind_constraint_get_offset (ClutterBindConstraint *bind)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BIND_CONSTRAINT (bind), 0.0);
|
||||
|
||||
return bind->offset;
|
||||
}
|
62
mutter/clutter/clutter/clutter-bind-constraint.h
Normal file
62
mutter/clutter/clutter/clutter-bind-constraint.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-constraint.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BIND_CONSTRAINT (clutter_bind_constraint_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ClutterBindConstraint, clutter_bind_constraint,
|
||||
CLUTTER, BIND_CONSTRAINT, ClutterConstraint)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterConstraint * clutter_bind_constraint_new (ClutterActor *source,
|
||||
ClutterBindCoordinate coordinate,
|
||||
gfloat offset);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_bind_constraint_set_source (ClutterBindConstraint *constraint,
|
||||
ClutterActor *source);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_bind_constraint_get_source (ClutterBindConstraint *constraint);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_bind_constraint_set_coordinate (ClutterBindConstraint *constraint,
|
||||
ClutterBindCoordinate coordinate);
|
||||
CLUTTER_EXPORT
|
||||
ClutterBindCoordinate clutter_bind_constraint_get_coordinate (ClutterBindConstraint *constraint);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_bind_constraint_set_offset (ClutterBindConstraint *constraint,
|
||||
gfloat offset);
|
||||
CLUTTER_EXPORT
|
||||
gfloat clutter_bind_constraint_get_offset (ClutterBindConstraint *constraint);
|
||||
|
||||
G_END_DECLS
|
898
mutter/clutter/clutter/clutter-binding-pool.c
Normal file
898
mutter/clutter/clutter/clutter-binding-pool.c
Normal file
@ -0,0 +1,898 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterBindingPool
|
||||
*
|
||||
* Pool for key bindings
|
||||
*
|
||||
* #ClutterBindingPool is a data structure holding a set of key bindings.
|
||||
* Each key binding associates a key symbol (eventually with modifiers)
|
||||
* to an action. A callback function is associated to each action.
|
||||
*
|
||||
* For a given key symbol and modifier mask combination there can be only one
|
||||
* action; for each action there can be only one callback. There can be
|
||||
* multiple actions with the same name, and the same callback can be used
|
||||
* to handle multiple key bindings.
|
||||
*
|
||||
* Actors requiring key bindings should create a new #ClutterBindingPool
|
||||
* inside their class initialization function and then install actions
|
||||
* like this:
|
||||
*
|
||||
* ```c
|
||||
* static void
|
||||
* foo_class_init (FooClass *klass)
|
||||
* {
|
||||
* ClutterBindingPool *binding_pool;
|
||||
*
|
||||
* binding_pool = clutter_binding_pool_get_for_class (klass);
|
||||
*
|
||||
* clutter_binding_pool_install_action (binding_pool, "move-up",
|
||||
* CLUTTER_Up, 0,
|
||||
* G_CALLBACK (foo_action_move_up),
|
||||
* NULL, NULL);
|
||||
* clutter_binding_pool_install_action (binding_pool, "move-up",
|
||||
* CLUTTER_KP_Up, 0,
|
||||
* G_CALLBACK (foo_action_move_up),
|
||||
* NULL, NULL);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The callback has a signature of:
|
||||
*
|
||||
* ```c
|
||||
* gboolean (* callback) (GObject *instance,
|
||||
* const gchar *action_name,
|
||||
* guint key_val,
|
||||
* ClutterModifierType modifiers,
|
||||
* gpointer user_data);
|
||||
* ```
|
||||
*
|
||||
* The actor should then override the [signal@Actor::key-press-event] and
|
||||
* use [method@BindingPool.activate] to match a [struct@Event] key event
|
||||
* structure to one of the actions:
|
||||
*
|
||||
* ```c
|
||||
* ClutterBindingPool *pool;
|
||||
*
|
||||
* // retrieve the binding pool for the type of the actor
|
||||
* pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor));
|
||||
*
|
||||
* // activate any callback matching the key symbol and modifiers
|
||||
* // mask of the key event. the returned value can be directly
|
||||
* // used to signal that the actor has handled the event.
|
||||
* return clutter_binding_pool_activate (pool,
|
||||
* key_event->keyval,
|
||||
* key_event->modifier_state,
|
||||
* G_OBJECT (actor));
|
||||
* ```
|
||||
*
|
||||
* The [method@BindingPool.activate] function will return %FALSE if
|
||||
* no action for the given key binding was found, if the action was
|
||||
* blocked (using [method@BindingPool.block_action]) or if the
|
||||
* key binding handler returned %FALSE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-binding-pool.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-marshal.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
#define BINDING_MOD_MASK ((CLUTTER_SHIFT_MASK | \
|
||||
CLUTTER_CONTROL_MASK | \
|
||||
CLUTTER_MOD1_MASK | \
|
||||
CLUTTER_SUPER_MASK | \
|
||||
CLUTTER_HYPER_MASK | \
|
||||
CLUTTER_META_MASK) | CLUTTER_RELEASE_MASK)
|
||||
|
||||
typedef struct _ClutterBindingEntry ClutterBindingEntry;
|
||||
|
||||
static GSList *clutter_binding_pools = NULL;
|
||||
static GQuark key_class_bindings = 0;
|
||||
|
||||
struct _ClutterBindingPool
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gchar *name; /* interned string, do not free */
|
||||
|
||||
GSList *entries;
|
||||
GHashTable *entries_hash;
|
||||
};
|
||||
|
||||
struct _ClutterBindingEntry
|
||||
{
|
||||
gchar *name; /* interned string, do not free */
|
||||
|
||||
guint key_val;
|
||||
ClutterModifierType modifiers;
|
||||
|
||||
GClosure *closure;
|
||||
|
||||
guint is_blocked : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_NAME,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_FINAL_TYPE (ClutterBindingPool, clutter_binding_pool, G_TYPE_OBJECT);
|
||||
|
||||
static guint
|
||||
binding_entry_hash (gconstpointer v)
|
||||
{
|
||||
const ClutterBindingEntry *e = v;
|
||||
guint h;
|
||||
|
||||
h = e->key_val;
|
||||
h ^= e->modifiers;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static gint
|
||||
binding_entry_compare (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
const ClutterBindingEntry *e1 = v1;
|
||||
const ClutterBindingEntry *e2 = v2;
|
||||
|
||||
return (e1->key_val == e2->key_val && e1->modifiers == e2->modifiers);
|
||||
}
|
||||
|
||||
static ClutterBindingEntry *
|
||||
binding_entry_new (const gchar *name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
ClutterBindingEntry *entry;
|
||||
|
||||
modifiers = modifiers & BINDING_MOD_MASK;
|
||||
|
||||
entry = g_new0 (ClutterBindingEntry, 1);
|
||||
entry->key_val = key_val;
|
||||
entry->modifiers = modifiers;
|
||||
entry->name = (gchar *) g_intern_string (name);
|
||||
entry->closure = NULL;
|
||||
entry->is_blocked = FALSE;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static ClutterBindingEntry *
|
||||
binding_pool_lookup_entry (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
ClutterBindingEntry lookup_entry = { 0, };
|
||||
|
||||
lookup_entry.key_val = key_val;
|
||||
lookup_entry.modifiers = modifiers;
|
||||
|
||||
return g_hash_table_lookup (pool->entries_hash, &lookup_entry);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_entry_free (gpointer data)
|
||||
{
|
||||
if (G_LIKELY (data))
|
||||
{
|
||||
ClutterBindingEntry *entry = data;
|
||||
|
||||
g_closure_unref (entry->closure);
|
||||
|
||||
g_free (entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_binding_pool_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject);
|
||||
|
||||
/* remove from the pools */
|
||||
clutter_binding_pools = g_slist_remove (clutter_binding_pools, pool);
|
||||
|
||||
g_hash_table_destroy (pool->entries_hash);
|
||||
|
||||
g_slist_free_full (pool->entries, (GDestroyNotify) binding_entry_free);
|
||||
|
||||
G_OBJECT_CLASS (clutter_binding_pool_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_binding_pool_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
pool->name = (gchar *) g_intern_string (g_value_get_string (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_binding_pool_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, pool->name);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_binding_pool_constructed (GObject *gobject)
|
||||
{
|
||||
ClutterBindingPool *pool = CLUTTER_BINDING_POOL (gobject);
|
||||
|
||||
/* bad monkey! bad, bad monkey! */
|
||||
if (G_UNLIKELY (pool->name == NULL))
|
||||
g_critical ("No name set for ClutterBindingPool %p", pool);
|
||||
|
||||
if (G_OBJECT_CLASS (clutter_binding_pool_parent_class)->constructed)
|
||||
G_OBJECT_CLASS (clutter_binding_pool_parent_class)->constructed (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_binding_pool_class_init (ClutterBindingPoolClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->constructed = clutter_binding_pool_constructed;
|
||||
gobject_class->set_property = clutter_binding_pool_set_property;
|
||||
gobject_class->get_property = clutter_binding_pool_get_property;
|
||||
gobject_class->finalize = clutter_binding_pool_finalize;
|
||||
|
||||
/**
|
||||
* ClutterBindingPool:name:
|
||||
*
|
||||
* The unique name of the #ClutterBindingPool.
|
||||
*/
|
||||
obj_props[PROP_NAME] =
|
||||
g_param_spec_string ("name", NULL, NULL,
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class,
|
||||
PROP_LAST,
|
||||
obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_binding_pool_init (ClutterBindingPool *pool)
|
||||
{
|
||||
pool->name = NULL;
|
||||
pool->entries = NULL;
|
||||
pool->entries_hash = g_hash_table_new (binding_entry_hash,
|
||||
binding_entry_compare);
|
||||
|
||||
clutter_binding_pools = g_slist_prepend (clutter_binding_pools, pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_new:
|
||||
* @name: the name of the binding pool
|
||||
*
|
||||
* Creates a new #ClutterBindingPool that can be used to store
|
||||
* key bindings for an actor. The @name must be a unique identifier
|
||||
* for the binding pool, so that [func@Clutter.BindingPool.find] will
|
||||
* be able to return the correct binding pool.
|
||||
*
|
||||
* Return value: the newly created binding pool with the given
|
||||
* name. Use g_object_unref() when done.
|
||||
*/
|
||||
ClutterBindingPool *
|
||||
clutter_binding_pool_new (const gchar *name)
|
||||
{
|
||||
ClutterBindingPool *pool;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
pool = clutter_binding_pool_find (name);
|
||||
if (G_UNLIKELY (pool))
|
||||
{
|
||||
g_warning ("A binding pool named '%s' is already present "
|
||||
"in the binding pools list",
|
||||
pool->name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_BINDING_POOL, "name", name, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_get_for_class:
|
||||
* @klass: a #GObjectClass pointer
|
||||
*
|
||||
* Retrieves the #ClutterBindingPool for the given #GObject class
|
||||
* and, eventually, creates it. This function is a wrapper around
|
||||
* [ctor@Clutter.BindingPool.new] and uses the class type name as the
|
||||
* unique name for the binding pool.
|
||||
*
|
||||
* Calling this function multiple times will return the same
|
||||
* #ClutterBindingPool.
|
||||
*
|
||||
* A binding pool for a class can also be retrieved using
|
||||
* [func@Clutter.BindingPool.find] with the class type name:
|
||||
*
|
||||
* ```
|
||||
* pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (instance));
|
||||
* ```
|
||||
*
|
||||
* Return value: (transfer none): the binding pool for the given class.
|
||||
* The returned #ClutterBindingPool is owned by Clutter and should not
|
||||
* be freed directly
|
||||
*/
|
||||
ClutterBindingPool *
|
||||
clutter_binding_pool_get_for_class (gpointer klass)
|
||||
{
|
||||
ClutterBindingPool *pool;
|
||||
|
||||
g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), NULL);
|
||||
|
||||
if (G_UNLIKELY (key_class_bindings == 0))
|
||||
key_class_bindings = g_quark_from_static_string ("clutter-bindings-set");
|
||||
|
||||
pool = g_dataset_id_get_data (klass, key_class_bindings);
|
||||
if (pool)
|
||||
return pool;
|
||||
|
||||
pool = clutter_binding_pool_new (G_OBJECT_CLASS_NAME (klass));
|
||||
g_dataset_id_set_data_full (klass, key_class_bindings,
|
||||
pool,
|
||||
g_object_unref);
|
||||
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_find:
|
||||
* @name: the name of the binding pool to find
|
||||
*
|
||||
* Finds the #ClutterBindingPool with @name.
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the #ClutterBindingPool, or %NULL
|
||||
*/
|
||||
ClutterBindingPool *
|
||||
clutter_binding_pool_find (const gchar *name)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
for (l = clutter_binding_pools; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterBindingPool *pool = l->data;
|
||||
|
||||
if (g_str_equal (pool->name, (gpointer) name))
|
||||
return pool;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_install_action:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @action_name: the name of the action
|
||||
* @key_val: key symbol
|
||||
* @modifiers: bitmask of modifiers
|
||||
* @callback: function to be called
|
||||
* when the action is activated
|
||||
* @data: data to be passed to @callback
|
||||
* @notify: function to be called when the action is removed
|
||||
* from the pool
|
||||
*
|
||||
* Installs a new action inside a #ClutterBindingPool. The action
|
||||
* is bound to @key_val and @modifiers.
|
||||
*
|
||||
* The same action name can be used for multiple @key_val, @modifiers
|
||||
* pairs.
|
||||
*
|
||||
* When an action has been activated using [method@Clutter.BindingPool.activate]
|
||||
* the passed @callback will be invoked (with @data).
|
||||
*
|
||||
* Actions can be blocked with [method@Clutter.BindingPool.block_action]
|
||||
* and then unblocked using [method@Clutter.BindingPool.unblock_action].
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_install_action (ClutterBindingPool *pool,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GCallback callback,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
ClutterBindingEntry *entry;
|
||||
GClosure *closure;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (action_name != NULL);
|
||||
g_return_if_fail (key_val != 0);
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
entry = binding_pool_lookup_entry (pool, key_val, modifiers);
|
||||
if (G_UNLIKELY (entry))
|
||||
{
|
||||
g_warning ("There already is an action '%s' for the given "
|
||||
"key symbol of %d (modifiers: %d) installed inside "
|
||||
"the binding pool.",
|
||||
entry->name,
|
||||
entry->key_val, entry->modifiers);
|
||||
return;
|
||||
}
|
||||
else
|
||||
entry = binding_entry_new (action_name, key_val, modifiers);
|
||||
|
||||
closure = g_cclosure_new (callback, data, (GClosureNotify) notify);
|
||||
entry->closure = g_closure_ref (closure);
|
||||
g_closure_sink (closure);
|
||||
|
||||
if (G_CLOSURE_NEEDS_MARSHAL (closure))
|
||||
{
|
||||
GClosureMarshal marshal;
|
||||
|
||||
marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS;
|
||||
g_closure_set_marshal (closure, marshal);
|
||||
}
|
||||
|
||||
pool->entries = g_slist_prepend (pool->entries, entry);
|
||||
g_hash_table_insert (pool->entries_hash, entry, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_install_closure:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @action_name: the name of the action
|
||||
* @key_val: key symbol
|
||||
* @modifiers: bitmask of modifiers
|
||||
* @closure: a #GClosure
|
||||
*
|
||||
* A #GClosure variant of [method@Clutter.BindingPool.install_action].
|
||||
*
|
||||
* Installs a new action inside a #ClutterBindingPool. The action
|
||||
* is bound to @key_val and @modifiers.
|
||||
*
|
||||
* The same action name can be used for multiple @key_val, @modifiers
|
||||
* pairs.
|
||||
*
|
||||
* When an action has been activated using [method@Clutter.BindingPool.activate]
|
||||
* the passed @closure will be invoked.
|
||||
*
|
||||
* Actions can be blocked with [method@Clutter.BindingPool.block_action]
|
||||
* and then unblocked using [method@Clutter.BindingPool.unblock_action].
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_install_closure (ClutterBindingPool *pool,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GClosure *closure)
|
||||
{
|
||||
ClutterBindingEntry *entry;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (action_name != NULL);
|
||||
g_return_if_fail (key_val != 0);
|
||||
g_return_if_fail (closure != NULL);
|
||||
|
||||
entry = binding_pool_lookup_entry (pool, key_val, modifiers);
|
||||
if (G_UNLIKELY (entry))
|
||||
{
|
||||
g_warning ("There already is an action '%s' for the given "
|
||||
"key symbol of %d (modifiers: %d) installed inside "
|
||||
"the binding pool.",
|
||||
entry->name,
|
||||
entry->key_val, entry->modifiers);
|
||||
return;
|
||||
}
|
||||
else
|
||||
entry = binding_entry_new (action_name, key_val, modifiers);
|
||||
|
||||
entry->closure = g_closure_ref (closure);
|
||||
g_closure_sink (closure);
|
||||
|
||||
if (G_CLOSURE_NEEDS_MARSHAL (closure))
|
||||
{
|
||||
GClosureMarshal marshal;
|
||||
|
||||
marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS;
|
||||
g_closure_set_marshal (closure, marshal);
|
||||
}
|
||||
|
||||
pool->entries = g_slist_prepend (pool->entries, entry);
|
||||
g_hash_table_insert (pool->entries_hash, entry, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_override_action:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @key_val: key symbol
|
||||
* @modifiers: bitmask of modifiers
|
||||
* @callback: function to be called when the action is activated
|
||||
* @data: data to be passed to @callback
|
||||
* @notify: function to be called when the action is removed
|
||||
* from the pool
|
||||
*
|
||||
* Allows overriding the action for @key_val and @modifiers inside a
|
||||
* #ClutterBindingPool. See [method@Clutter.BindingPool.install_action].
|
||||
*
|
||||
* When an action has been activated using [method@Clutter.BindingPool.activate]
|
||||
* the passed @callback will be invoked (with @data).
|
||||
*
|
||||
* Actions can be blocked with [method@Clutter.BindingPool.block_action]
|
||||
* and then unblocked using [method@Clutter.BindingPool.unblock_action].
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_override_action (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GCallback callback,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
ClutterBindingEntry *entry;
|
||||
GClosure *closure;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (key_val != 0);
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
entry = binding_pool_lookup_entry (pool, key_val, modifiers);
|
||||
if (G_UNLIKELY (entry == NULL))
|
||||
{
|
||||
g_warning ("There is no action for the given key symbol "
|
||||
"of %d (modifiers: %d) installed inside the "
|
||||
"binding pool.",
|
||||
key_val, modifiers);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->closure)
|
||||
{
|
||||
g_closure_unref (entry->closure);
|
||||
entry->closure = NULL;
|
||||
}
|
||||
|
||||
closure = g_cclosure_new (callback, data, (GClosureNotify) notify);
|
||||
entry->closure = g_closure_ref (closure);
|
||||
g_closure_sink (closure);
|
||||
|
||||
if (G_CLOSURE_NEEDS_MARSHAL (closure))
|
||||
{
|
||||
GClosureMarshal marshal;
|
||||
|
||||
marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS;
|
||||
g_closure_set_marshal (closure, marshal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_override_closure:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @key_val: key symbol
|
||||
* @modifiers: bitmask of modifiers
|
||||
* @closure: a #GClosure
|
||||
*
|
||||
* A #GClosure variant of [method@Clutter.BindingPool.override_action].
|
||||
*
|
||||
* Allows overriding the action for @key_val and @modifiers inside a
|
||||
* #ClutterBindingPool. See [method@Clutter.BindingPool.install_closure].
|
||||
*
|
||||
* When an action has been activated using [method@Clutter.BindingPool.activate]
|
||||
* the passed @callback will be invoked (with @data).
|
||||
*
|
||||
* Actions can be blocked with [method@Clutter.BindingPool.block_action]
|
||||
* and then unblocked using [method@Clutter.BindingPool.unblock_action].
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_override_closure (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GClosure *closure)
|
||||
{
|
||||
ClutterBindingEntry *entry;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (key_val != 0);
|
||||
g_return_if_fail (closure != NULL);
|
||||
|
||||
entry = binding_pool_lookup_entry (pool, key_val, modifiers);
|
||||
if (G_UNLIKELY (entry == NULL))
|
||||
{
|
||||
g_warning ("There is no action for the given key symbol "
|
||||
"of %d (modifiers: %d) installed inside the "
|
||||
"binding pool.",
|
||||
key_val, modifiers);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->closure)
|
||||
{
|
||||
g_closure_unref (entry->closure);
|
||||
entry->closure = NULL;
|
||||
}
|
||||
|
||||
entry->closure = g_closure_ref (closure);
|
||||
g_closure_sink (closure);
|
||||
|
||||
if (G_CLOSURE_NEEDS_MARSHAL (closure))
|
||||
{
|
||||
GClosureMarshal marshal;
|
||||
|
||||
marshal = _clutter_marshal_BOOLEAN__STRING_UINT_FLAGS;
|
||||
g_closure_set_marshal (closure, marshal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_find_action:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @key_val: a key symbol
|
||||
* @modifiers: a bitmask for the modifiers
|
||||
*
|
||||
* Retrieves the name of the action matching the given key symbol
|
||||
* and modifiers bitmask.
|
||||
*
|
||||
* Return value: the name of the action, if found, or %NULL. The
|
||||
* returned string is owned by the binding pool and should never
|
||||
* be modified or freed
|
||||
*/
|
||||
const gchar *
|
||||
clutter_binding_pool_find_action (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
ClutterBindingEntry *entry;
|
||||
|
||||
g_return_val_if_fail (pool != NULL, NULL);
|
||||
g_return_val_if_fail (key_val != 0, NULL);
|
||||
|
||||
entry = binding_pool_lookup_entry (pool, key_val, modifiers);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
return entry->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_remove_action:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @key_val: a key symbol
|
||||
* @modifiers: a bitmask for the modifiers
|
||||
*
|
||||
* Removes the action matching the given @key_val, @modifiers pair,
|
||||
* if any exists.
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_remove_action (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers)
|
||||
{
|
||||
ClutterBindingEntry remove_entry = { 0, };
|
||||
GSList *l;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (key_val != 0);
|
||||
|
||||
modifiers = modifiers & BINDING_MOD_MASK;
|
||||
|
||||
remove_entry.key_val = key_val;
|
||||
remove_entry.modifiers = modifiers;
|
||||
|
||||
for (l = pool->entries; l != NULL; l = l->data)
|
||||
{
|
||||
ClutterBindingEntry *e = l->data;
|
||||
|
||||
if (e->key_val == remove_entry.key_val &&
|
||||
e->modifiers == remove_entry.modifiers)
|
||||
{
|
||||
pool->entries = g_slist_remove_link (pool->entries, l);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_remove (pool->entries_hash, &remove_entry);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_binding_entry_invoke (ClutterBindingEntry *entry,
|
||||
GObject *gobject)
|
||||
{
|
||||
GValue params[4] = {
|
||||
G_VALUE_INIT,
|
||||
G_VALUE_INIT,
|
||||
G_VALUE_INIT,
|
||||
G_VALUE_INIT
|
||||
};
|
||||
GValue result = G_VALUE_INIT;
|
||||
gboolean retval = TRUE;
|
||||
|
||||
g_value_init (¶ms[0], G_TYPE_OBJECT);
|
||||
g_value_set_object (¶ms[0], gobject);
|
||||
|
||||
g_value_init (¶ms[1], G_TYPE_STRING);
|
||||
g_value_set_static_string (¶ms[1], entry->name);
|
||||
|
||||
g_value_init (¶ms[2], G_TYPE_UINT);
|
||||
g_value_set_uint (¶ms[2], entry->key_val);
|
||||
|
||||
g_value_init (¶ms[3], CLUTTER_TYPE_MODIFIER_TYPE);
|
||||
g_value_set_flags (¶ms[3], entry->modifiers);
|
||||
|
||||
g_value_init (&result, G_TYPE_BOOLEAN);
|
||||
|
||||
g_closure_invoke (entry->closure, &result, 4, params, NULL);
|
||||
|
||||
retval = g_value_get_boolean (&result);
|
||||
|
||||
g_value_unset (&result);
|
||||
|
||||
g_value_unset (¶ms[0]);
|
||||
g_value_unset (¶ms[1]);
|
||||
g_value_unset (¶ms[2]);
|
||||
g_value_unset (¶ms[3]);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_activate:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @key_val: the key symbol
|
||||
* @modifiers: bitmask for the modifiers
|
||||
* @gobject: a #GObject
|
||||
*
|
||||
* Activates the callback associated to the action that is
|
||||
* bound to the @key_val and @modifiers pair.
|
||||
*
|
||||
* The callback has the following signature:
|
||||
*
|
||||
* ```
|
||||
* void (* callback) (GObject *gobject,
|
||||
* const gchar *action_name,
|
||||
* guint key_val,
|
||||
* ClutterModifierType modifiers,
|
||||
* gpointer user_data);
|
||||
* ```
|
||||
*
|
||||
* Where the #GObject instance is @gobject and the user data
|
||||
* is the one passed when installing the action with
|
||||
* [method@Clutter.BindingPool.install_action].
|
||||
*
|
||||
* If the action bound to the @key_val, @modifiers pair has been
|
||||
* blocked using [method@Clutter.BindingPool.block_action], the callback
|
||||
* will not be invoked, and this function will return %FALSE.
|
||||
*
|
||||
* Return value: %TRUE if an action was found and was activated
|
||||
*/
|
||||
gboolean
|
||||
clutter_binding_pool_activate (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GObject *gobject)
|
||||
{
|
||||
ClutterBindingEntry *entry = NULL;
|
||||
|
||||
g_return_val_if_fail (pool != NULL, FALSE);
|
||||
g_return_val_if_fail (key_val != 0, FALSE);
|
||||
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
|
||||
|
||||
modifiers = (modifiers & BINDING_MOD_MASK);
|
||||
|
||||
entry = binding_pool_lookup_entry (pool, key_val, modifiers);
|
||||
if (!entry)
|
||||
return FALSE;
|
||||
|
||||
if (!entry->is_blocked)
|
||||
return clutter_binding_entry_invoke (entry, gobject);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_block_action:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @action_name: an action name
|
||||
*
|
||||
* Blocks all the actions with name @action_name inside @pool.
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_block_action (ClutterBindingPool *pool,
|
||||
const gchar *action_name)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (action_name != NULL);
|
||||
|
||||
for (l = pool->entries; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterBindingEntry *entry = l->data;
|
||||
|
||||
if (g_str_equal (entry->name, (gpointer) action_name))
|
||||
entry->is_blocked = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_binding_pool_unblock_action:
|
||||
* @pool: a #ClutterBindingPool
|
||||
* @action_name: an action name
|
||||
*
|
||||
* Unblockes all the actions with name @action_name inside @pool.
|
||||
*
|
||||
* Unblocking an action does not cause the callback bound to it to
|
||||
* be invoked in case [method@Clutter.BindingPool.activate] was called on
|
||||
* an action previously blocked with [method@Clutter.BindingPool.block_action].
|
||||
*/
|
||||
void
|
||||
clutter_binding_pool_unblock_action (ClutterBindingPool *pool,
|
||||
const gchar *action_name)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
g_return_if_fail (pool != NULL);
|
||||
g_return_if_fail (action_name != NULL);
|
||||
|
||||
for (l = pool->entries; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterBindingEntry *entry = l->data;
|
||||
|
||||
if (g_str_equal (entry->name, (gpointer) action_name))
|
||||
entry->is_blocked = FALSE;
|
||||
}
|
||||
}
|
101
mutter/clutter/clutter/clutter-binding-pool.h
Normal file
101
mutter/clutter/clutter/clutter-binding-pool.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter/clutter-event.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BINDING_POOL (clutter_binding_pool_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ClutterBindingPool,
|
||||
clutter_binding_pool,
|
||||
CLUTTER,
|
||||
BINDING_POOL,
|
||||
GObject)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterBindingPool * clutter_binding_pool_new (const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
ClutterBindingPool * clutter_binding_pool_get_for_class (gpointer klass);
|
||||
CLUTTER_EXPORT
|
||||
ClutterBindingPool * clutter_binding_pool_find (const gchar *name);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_install_action (ClutterBindingPool *pool,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GCallback callback,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_install_closure (ClutterBindingPool *pool,
|
||||
const gchar *action_name,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GClosure *closure);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_override_action (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GCallback callback,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_override_closure (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GClosure *closure);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_binding_pool_find_action (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_remove_action (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_binding_pool_activate (ClutterBindingPool *pool,
|
||||
guint key_val,
|
||||
ClutterModifierType modifiers,
|
||||
GObject *gobject);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_block_action (ClutterBindingPool *pool,
|
||||
const gchar *action_name);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_binding_pool_unblock_action (ClutterBindingPool *pool,
|
||||
const gchar *action_name);
|
||||
|
||||
G_END_DECLS
|
203
mutter/clutter/clutter/clutter-blur-effect.c
Normal file
203
mutter/clutter/clutter/clutter-blur-effect.c
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterBlurEffect:
|
||||
*
|
||||
* A blur effect
|
||||
*
|
||||
* #ClutterBlurEffect is a sub-class of #ClutterEffect that allows blurring a
|
||||
* actor and its contents.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-blur-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
#define BLUR_PADDING 2
|
||||
|
||||
/* FIXME - lame shader; we should really have a decoupled
|
||||
* horizontal/vertical two pass shader for the gaussian blur
|
||||
*/
|
||||
static const gchar *box_blur_glsl_declarations =
|
||||
"uniform vec2 pixel_step;\n";
|
||||
#define SAMPLE(offx, offy) \
|
||||
"cogl_texel += texture2D (cogl_sampler, cogl_tex_coord.st + pixel_step * " \
|
||||
"vec2 (" G_STRINGIFY (offx) ", " G_STRINGIFY (offy) "));\n"
|
||||
static const gchar *box_blur_glsl_shader =
|
||||
" cogl_texel = texture2D (cogl_sampler, cogl_tex_coord.st);\n"
|
||||
SAMPLE (-1.0, -1.0)
|
||||
SAMPLE ( 0.0, -1.0)
|
||||
SAMPLE (+1.0, -1.0)
|
||||
SAMPLE (-1.0, 0.0)
|
||||
SAMPLE (+1.0, 0.0)
|
||||
SAMPLE (-1.0, +1.0)
|
||||
SAMPLE ( 0.0, +1.0)
|
||||
SAMPLE (+1.0, +1.0)
|
||||
" cogl_texel /= 9.0;\n";
|
||||
#undef SAMPLE
|
||||
|
||||
typedef struct _ClutterBlurEffectPrivate
|
||||
{
|
||||
/* a back pointer to our actor, so that we can query it */
|
||||
ClutterActor *actor;
|
||||
|
||||
gint pixel_step_uniform;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
} ClutterBlurEffectPrivate;
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (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);
|
||||
ClutterBlurEffectPrivate *priv =
|
||||
clutter_blur_effect_get_instance_private (blur_effect);
|
||||
|
||||
if (priv->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 (priv->pipeline,
|
||||
priv->pixel_step_uniform,
|
||||
2, /* n_components */
|
||||
1, /* count */
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
|
||||
return g_object_ref (priv->pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_blur_effect_modify_paint_volume (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
gfloat cur_width, cur_height;
|
||||
graphene_point3d_t origin;
|
||||
|
||||
clutter_paint_volume_get_origin (volume, &origin);
|
||||
cur_width = clutter_paint_volume_get_width (volume);
|
||||
cur_height = clutter_paint_volume_get_height (volume);
|
||||
|
||||
origin.x -= BLUR_PADDING;
|
||||
origin.y -= BLUR_PADDING;
|
||||
cur_width += 2 * BLUR_PADDING;
|
||||
cur_height += 2 * BLUR_PADDING;
|
||||
clutter_paint_volume_set_origin (volume, &origin);
|
||||
clutter_paint_volume_set_width (volume, cur_width);
|
||||
clutter_paint_volume_set_height (volume, cur_height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_effect_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (gobject);
|
||||
ClutterBlurEffectPrivate *priv =
|
||||
clutter_blur_effect_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->pipeline);
|
||||
|
||||
G_OBJECT_CLASS (clutter_blur_effect_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_effect_class_init (ClutterBlurEffectClass *klass)
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
gobject_class->dispose = clutter_blur_effect_dispose;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_effect_init (ClutterBlurEffect *self)
|
||||
{
|
||||
ClutterBlurEffectClass *klass = CLUTTER_BLUR_EFFECT_GET_CLASS (self);
|
||||
ClutterBlurEffectPrivate *priv =
|
||||
clutter_blur_effect_get_instance_private (self);
|
||||
|
||||
if (G_UNLIKELY (klass->base_pipeline == NULL))
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
klass->base_pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
box_blur_glsl_declarations,
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet, box_blur_glsl_shader);
|
||||
cogl_pipeline_add_layer_snippet (klass->base_pipeline, 0, snippet);
|
||||
g_object_unref (snippet);
|
||||
|
||||
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
|
||||
}
|
||||
|
||||
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
||||
|
||||
priv->pixel_step_uniform =
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline, "pixel_step");
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_effect_new:
|
||||
*
|
||||
* Creates a new #ClutterBlurEffect to be used with
|
||||
* [method@Clutter.Actor.add_effect]
|
||||
*
|
||||
* Return value: the newly created #ClutterBlurEffect or %NULL
|
||||
*/
|
||||
ClutterEffect *
|
||||
clutter_blur_effect_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_BLUR_EFFECT, NULL);
|
||||
}
|
54
mutter/clutter/clutter/clutter-blur-effect.h
Normal file
54
mutter/clutter/clutter/clutter-blur-effect.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-effect.h"
|
||||
#include "clutter/clutter-offscreen-effect.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BLUR_EFFECT (clutter_blur_effect_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterBlurEffect,
|
||||
clutter_blur_effect,
|
||||
CLUTTER, BLUR_EFFECT,
|
||||
ClutterOffscreenEffect)
|
||||
|
||||
struct _ClutterBlurEffectClass
|
||||
{
|
||||
ClutterOffscreenEffectClass parent_class;
|
||||
|
||||
CoglPipeline *base_pipeline;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterEffect *clutter_blur_effect_new (void);
|
||||
|
||||
G_END_DECLS
|
37
mutter/clutter/clutter/clutter-blur-private.h
Normal file
37
mutter/clutter/clutter/clutter-blur-private.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterBlur ClutterBlur;
|
||||
|
||||
ClutterBlur * clutter_blur_new (CoglTexture *texture,
|
||||
float radius);
|
||||
|
||||
void clutter_blur_apply (ClutterBlur *blur);
|
||||
|
||||
CoglTexture * clutter_blur_get_texture (ClutterBlur *blur);
|
||||
|
||||
void clutter_blur_free (ClutterBlur *blur);
|
||||
|
||||
G_END_DECLS
|
436
mutter/clutter/clutter/clutter-blur.c
Normal file
436
mutter/clutter/clutter/clutter-blur.c
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
* 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 "config.h"
|
||||
|
||||
#include "clutter/clutter-blur-private.h"
|
||||
|
||||
#include "clutter/clutter-backend.h"
|
||||
|
||||
/**
|
||||
* ClutterBlur:
|
||||
*
|
||||
* 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);
|
||||
g_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_object (&pass->texture);
|
||||
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_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_4f (&transparent, 0.0, 0.0, 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_object (&pass->pipeline);
|
||||
g_clear_object (&pass->texture);
|
||||
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 radius)
|
||||
{
|
||||
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 (radius >= 0.0, NULL);
|
||||
|
||||
width = cogl_texture_get_width (texture);
|
||||
height = cogl_texture_get_height (texture);
|
||||
|
||||
blur = g_new0 (ClutterBlur, 1);
|
||||
blur->sigma = radius / 2.0;
|
||||
blur->source_texture = g_object_ref (texture);
|
||||
blur->downscale_factor = calculate_downscale_factor (width,
|
||||
height,
|
||||
blur->sigma);
|
||||
|
||||
if (G_APPROX_VALUE (blur->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
|
||||
* [method@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 [method@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]);
|
||||
g_clear_object (&blur->source_texture);
|
||||
g_free (blur);
|
||||
}
|
1148
mutter/clutter/clutter/clutter-box-layout.c
Normal file
1148
mutter/clutter/clutter/clutter-box-layout.c
Normal file
File diff suppressed because it is too large
Load Diff
72
mutter/clutter/clutter/clutter-box-layout.h
Normal file
72
mutter/clutter/clutter/clutter-box-layout.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Based on the NBTK NbtkBoxLayout actor by:
|
||||
* Thomas Wood <thomas.wood@intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-layout-manager.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BOX_LAYOUT (clutter_box_layout_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterBoxLayout,
|
||||
clutter_box_layout,
|
||||
CLUTTER, BOX_LAYOUT,
|
||||
ClutterLayoutManager)
|
||||
|
||||
struct _ClutterBoxLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManagerClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterLayoutManager * clutter_box_layout_new (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_box_layout_set_orientation (ClutterBoxLayout *layout,
|
||||
ClutterOrientation orientation);
|
||||
CLUTTER_EXPORT
|
||||
ClutterOrientation clutter_box_layout_get_orientation (ClutterBoxLayout *layout);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_box_layout_set_spacing (ClutterBoxLayout *layout,
|
||||
guint spacing);
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_box_layout_get_spacing (ClutterBoxLayout *layout);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_box_layout_set_homogeneous (ClutterBoxLayout *layout,
|
||||
gboolean homogeneous);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_box_layout_get_homogeneous (ClutterBoxLayout *layout);
|
||||
|
||||
G_END_DECLS
|
595
mutter/clutter/clutter/clutter-brightness-contrast-effect.c
Normal file
595
mutter/clutter/clutter/clutter-brightness-contrast-effect.c
Normal file
@ -0,0 +1,595 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010-2012 Inclusive Design Research Centre, OCAD University.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Joseph Scheuhammer <clown@alum.mit.edu>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterBrightnessContrastEffect:
|
||||
*
|
||||
* Increase/decrease brightness and/or contrast of actor.
|
||||
*
|
||||
* #ClutterBrightnessContrastEffect is a sub-class of #ClutterEffect that
|
||||
* changes the overall brightness of a #ClutterActor.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-brightness-contrast-effect.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
typedef struct _ClutterBrightnessContrastEffectPrivate
|
||||
{
|
||||
/* Brightness and contrast changes. */
|
||||
gfloat brightness_red;
|
||||
gfloat brightness_green;
|
||||
gfloat brightness_blue;
|
||||
|
||||
gfloat contrast_red;
|
||||
gfloat contrast_green;
|
||||
gfloat contrast_blue;
|
||||
|
||||
gint brightness_multiplier_uniform;
|
||||
gint brightness_offset_uniform;
|
||||
gint contrast_uniform;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
} ClutterBrightnessContrastEffectPrivate;
|
||||
|
||||
|
||||
/* Brightness effects in GLSL.
|
||||
*/
|
||||
static const gchar *brightness_contrast_decls =
|
||||
"uniform vec3 brightness_multiplier;\n"
|
||||
"uniform vec3 brightness_offset;\n"
|
||||
"uniform vec3 contrast;\n";
|
||||
|
||||
static const gchar *brightness_contrast_source =
|
||||
/* Apply the brightness. The brightness_offset is multiplied by the
|
||||
alpha to keep the color pre-multiplied */
|
||||
"cogl_color_out.rgb = (cogl_color_out.rgb * brightness_multiplier +\n"
|
||||
" brightness_offset * cogl_color_out.a);\n"
|
||||
/* Apply the contrast */
|
||||
"cogl_color_out.rgb = ((cogl_color_out.rgb - 0.5 * cogl_color_out.a) *\n"
|
||||
" contrast + 0.5 * cogl_color_out.a);\n";
|
||||
|
||||
static const ClutterColor no_brightness_change = { 0x7f, 0x7f, 0x7f, 0xff };
|
||||
static const ClutterColor no_contrast_change = { 0x7f, 0x7f, 0x7f, 0xff };
|
||||
static const gfloat no_change = 0.0f;
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_BRIGHTNESS,
|
||||
PROP_CONTRAST,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBrightnessContrastEffect,
|
||||
clutter_brightness_contrast_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT)
|
||||
|
||||
static gboolean
|
||||
will_have_no_effect (ClutterBrightnessContrastEffect *self)
|
||||
{
|
||||
ClutterBrightnessContrastEffectPrivate *priv =
|
||||
clutter_brightness_contrast_effect_get_instance_private (self);
|
||||
|
||||
return (G_APPROX_VALUE (priv->brightness_red, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (priv->brightness_green, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (priv->brightness_blue, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (priv->contrast_red, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (priv->contrast_green, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (priv->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);
|
||||
ClutterBrightnessContrastEffectPrivate *priv =
|
||||
clutter_brightness_contrast_effect_get_instance_private (self);
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
|
||||
return g_object_ref (priv->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 (will_have_no_effect (self))
|
||||
return FALSE;
|
||||
|
||||
parent_class =
|
||||
CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class);
|
||||
|
||||
return parent_class->pre_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (gobject);
|
||||
ClutterBrightnessContrastEffectPrivate *priv =
|
||||
clutter_brightness_contrast_effect_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->pipeline);
|
||||
|
||||
G_OBJECT_CLASS (clutter_brightness_contrast_effect_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *effect = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_BRIGHTNESS:
|
||||
{
|
||||
const ClutterColor *color = clutter_value_get_color (value);
|
||||
clutter_brightness_contrast_effect_set_brightness_full (effect,
|
||||
color->red / 127.0f - 1.0f,
|
||||
color->green / 127.0f - 1.0f,
|
||||
color->blue / 127.0f - 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_CONTRAST:
|
||||
{
|
||||
const ClutterColor *color = clutter_value_get_color (value);
|
||||
clutter_brightness_contrast_effect_set_contrast_full (effect,
|
||||
color->red / 127.0f - 1.0f,
|
||||
color->green / 127.0f - 1.0f,
|
||||
color->blue / 127.0f - 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBrightnessContrastEffect *effect = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (gobject);
|
||||
ClutterBrightnessContrastEffectPrivate *priv =
|
||||
clutter_brightness_contrast_effect_get_instance_private (effect);
|
||||
ClutterColor color;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_BRIGHTNESS:
|
||||
{
|
||||
color.red = (priv->brightness_red + 1.0f) * 127.0f;
|
||||
color.green = (priv->brightness_green + 1.0f) * 127.0f;
|
||||
color.blue = (priv->brightness_blue + 1.0f) * 127.0f;
|
||||
color.alpha = 0xff;
|
||||
|
||||
clutter_value_set_color (value, &color);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_CONTRAST:
|
||||
{
|
||||
color.red = (priv->contrast_red + 1.0f) * 127.0f;
|
||||
color.green = (priv->contrast_green + 1.0f) * 127.0f;
|
||||
color.blue = (priv->contrast_blue + 1.0f) * 127.0f;
|
||||
color.alpha = 0xff;
|
||||
|
||||
clutter_value_set_color (value, &color);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectClass *klass)
|
||||
{
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_brightness_contrast_effect_create_pipeline;
|
||||
|
||||
effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint;
|
||||
|
||||
gobject_class->set_property = clutter_brightness_contrast_effect_set_property;
|
||||
gobject_class->get_property = clutter_brightness_contrast_effect_get_property;
|
||||
gobject_class->dispose = clutter_brightness_contrast_effect_dispose;
|
||||
|
||||
/**
|
||||
* ClutterBrightnessContrastEffect:brightness:
|
||||
*
|
||||
* The brightness change to apply to the effect.
|
||||
*
|
||||
* This property uses a #ClutterColor to represent the changes to each
|
||||
* color channel. The range is [ 0, 255 ], with 127 as the value used
|
||||
* to indicate no change; values smaller than 127 indicate a decrease
|
||||
* in brightness, and values larger than 127 indicate an increase in
|
||||
* brightness.
|
||||
*/
|
||||
obj_props[PROP_BRIGHTNESS] =
|
||||
clutter_param_spec_color ("brightness", NULL, NULL,
|
||||
&no_brightness_change,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterBrightnessContrastEffect:contrast:
|
||||
*
|
||||
* The contrast change to apply to the effect.
|
||||
*
|
||||
* This property uses a #ClutterColor to represent the changes to each
|
||||
* color channel. The range is [ 0, 255 ], with 127 as the value used
|
||||
* to indicate no change; values smaller than 127 indicate a decrease
|
||||
* in contrast, and values larger than 127 indicate an increase in
|
||||
* contrast.
|
||||
*/
|
||||
obj_props[PROP_CONTRAST] =
|
||||
clutter_param_spec_color ("contrast", NULL, NULL,
|
||||
&no_contrast_change,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
get_brightness_values (gfloat value,
|
||||
gfloat *multiplier,
|
||||
gfloat *offset)
|
||||
{
|
||||
if (value < 0.0f)
|
||||
{
|
||||
*multiplier = 1.0f + value;
|
||||
*offset = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
*multiplier = 1.0f - value;
|
||||
*offset = value;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
update_uniforms (ClutterBrightnessContrastEffect *self)
|
||||
{
|
||||
ClutterBrightnessContrastEffectPrivate *priv =
|
||||
clutter_brightness_contrast_effect_get_instance_private (self);
|
||||
|
||||
if (priv->brightness_multiplier_uniform > -1 &&
|
||||
priv->brightness_offset_uniform > -1)
|
||||
{
|
||||
float brightness_multiplier[3];
|
||||
float brightness_offset[3];
|
||||
|
||||
get_brightness_values (priv->brightness_red,
|
||||
brightness_multiplier + 0,
|
||||
brightness_offset + 0);
|
||||
get_brightness_values (priv->brightness_green,
|
||||
brightness_multiplier + 1,
|
||||
brightness_offset + 1);
|
||||
get_brightness_values (priv->brightness_blue,
|
||||
brightness_multiplier + 2,
|
||||
brightness_offset + 2);
|
||||
|
||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
||||
priv->brightness_multiplier_uniform,
|
||||
3, /* n_components */
|
||||
1, /* count */
|
||||
brightness_multiplier);
|
||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
||||
priv->brightness_offset_uniform,
|
||||
3, /* n_components */
|
||||
1, /* count */
|
||||
brightness_offset);
|
||||
}
|
||||
|
||||
if (priv->contrast_uniform > -1)
|
||||
{
|
||||
float contrast[3] = {
|
||||
tan ((priv->contrast_red + 1) * G_PI_4),
|
||||
tan ((priv->contrast_green + 1) * G_PI_4),
|
||||
tan ((priv->contrast_blue + 1) * G_PI_4)
|
||||
};
|
||||
|
||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
||||
priv->contrast_uniform,
|
||||
3, /* n_components */
|
||||
1, /* count */
|
||||
contrast);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_brightness_contrast_effect_init (ClutterBrightnessContrastEffect *self)
|
||||
{
|
||||
ClutterBrightnessContrastEffectClass *klass;
|
||||
ClutterBrightnessContrastEffectPrivate *priv =
|
||||
clutter_brightness_contrast_effect_get_instance_private (self);
|
||||
|
||||
priv->brightness_red = no_change;
|
||||
priv->brightness_green = no_change;
|
||||
priv->brightness_blue = no_change;
|
||||
|
||||
priv->contrast_red = no_change;
|
||||
priv->contrast_green = no_change;
|
||||
priv->contrast_blue = no_change;
|
||||
|
||||
klass = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT_GET_CLASS (self);
|
||||
|
||||
if (G_UNLIKELY (klass->base_pipeline == NULL))
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
klass->base_pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
|
||||
brightness_contrast_decls,
|
||||
brightness_contrast_source);
|
||||
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
|
||||
g_object_unref (snippet);
|
||||
|
||||
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
|
||||
}
|
||||
|
||||
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
||||
|
||||
priv->brightness_multiplier_uniform =
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline,
|
||||
"brightness_multiplier");
|
||||
priv->brightness_offset_uniform =
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline,
|
||||
"brightness_offset");
|
||||
priv->contrast_uniform =
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline, "contrast");
|
||||
|
||||
update_uniforms (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_new:
|
||||
*
|
||||
* Creates a new #ClutterBrightnessContrastEffect to be used with
|
||||
* [method@Clutter.Actor.add_effect]
|
||||
*
|
||||
* Return value: (transfer full): the newly created
|
||||
* #ClutterBrightnessContrastEffect or %NULL. Use g_object_unref() when
|
||||
* done.
|
||||
*/
|
||||
ClutterEffect *
|
||||
clutter_brightness_contrast_effect_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_set_brightness_full:
|
||||
* @effect: a #ClutterBrightnessContrastEffect
|
||||
* @red: red component of the change in brightness
|
||||
* @green: green component of the change in brightness
|
||||
* @blue: blue component of the change in brightness
|
||||
*
|
||||
* The range for each component is [-1.0, 1.0] where 0.0 designates no change,
|
||||
* values below 0.0 mean a decrease in brightness, and values above indicate
|
||||
* an increase.
|
||||
*/
|
||||
void
|
||||
clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContrastEffect *effect,
|
||||
gfloat red,
|
||||
gfloat green,
|
||||
gfloat blue)
|
||||
{
|
||||
ClutterBrightnessContrastEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
priv = clutter_brightness_contrast_effect_get_instance_private (effect);
|
||||
if (G_APPROX_VALUE (red, priv->brightness_red, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (green, priv->brightness_green, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (blue, priv->brightness_blue, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
priv->brightness_red = red;
|
||||
priv->brightness_green = green;
|
||||
priv->brightness_blue = blue;
|
||||
|
||||
update_uniforms (effect);
|
||||
|
||||
clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_BRIGHTNESS]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_get_brightness:
|
||||
* @effect: a #ClutterBrightnessContrastEffect
|
||||
* @red: (out) (allow-none): return location for red component of the
|
||||
* change in brightness
|
||||
* @green: (out) (allow-none): return location for green component of the
|
||||
* change in brightness
|
||||
* @blue: (out) (allow-none): return location for blue component of the
|
||||
* change in brightness
|
||||
*
|
||||
* Retrieves the change in brightness used by @effect.
|
||||
*/
|
||||
void
|
||||
clutter_brightness_contrast_effect_get_brightness (ClutterBrightnessContrastEffect *effect,
|
||||
gfloat *red,
|
||||
gfloat *green,
|
||||
gfloat *blue)
|
||||
{
|
||||
ClutterBrightnessContrastEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
priv = clutter_brightness_contrast_effect_get_instance_private (effect);
|
||||
if (red != NULL)
|
||||
*red = priv->brightness_red;
|
||||
|
||||
if (green != NULL)
|
||||
*green = priv->brightness_green;
|
||||
|
||||
if (blue != NULL)
|
||||
*blue = priv->brightness_blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_set_brightness:
|
||||
* @effect: a #ClutterBrightnessContrastEffect
|
||||
* @brightness: the brightness change for all three components (r, g, b)
|
||||
*
|
||||
* The range of @brightness is [-1.0, 1.0], where 0.0 designates no change;
|
||||
* a value below 0.0 indicates a decrease in brightness; and a value
|
||||
* above 0.0 indicates an increase of brightness.
|
||||
*/
|
||||
void
|
||||
clutter_brightness_contrast_effect_set_brightness (ClutterBrightnessContrastEffect *effect,
|
||||
gfloat brightness)
|
||||
{
|
||||
clutter_brightness_contrast_effect_set_brightness_full (effect,
|
||||
brightness,
|
||||
brightness,
|
||||
brightness);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_set_contrast_full:
|
||||
* @effect: a #ClutterBrightnessContrastEffect
|
||||
* @red: red component of the change in contrast
|
||||
* @green: green component of the change in contrast
|
||||
* @blue: blue component of the change in contrast
|
||||
*
|
||||
* The range for each component is [-1.0, 1.0] where 0.0 designates no change,
|
||||
* values below 0.0 mean a decrease in contrast, and values above indicate
|
||||
* an increase.
|
||||
*/
|
||||
void
|
||||
clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastEffect *effect,
|
||||
gfloat red,
|
||||
gfloat green,
|
||||
gfloat blue)
|
||||
{
|
||||
ClutterBrightnessContrastEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
priv = clutter_brightness_contrast_effect_get_instance_private (effect);
|
||||
if (G_APPROX_VALUE (red, priv->contrast_red, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (green, priv->contrast_green, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (blue, priv->contrast_blue, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
priv->contrast_red = red;
|
||||
priv->contrast_green = green;
|
||||
priv->contrast_blue = blue;
|
||||
|
||||
update_uniforms (effect);
|
||||
|
||||
clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_CONTRAST]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_get_contrast:
|
||||
* @effect: a #ClutterBrightnessContrastEffect
|
||||
* @red: (out) (allow-none): return location for red component of the
|
||||
* change in contrast
|
||||
* @green: (out) (allow-none): return location for green component of the
|
||||
* change in contrast
|
||||
* @blue: (out) (allow-none): return location for blue component of the
|
||||
* change in contrast
|
||||
*
|
||||
* Retrieves the contrast value used by @effect.
|
||||
*/
|
||||
void
|
||||
clutter_brightness_contrast_effect_get_contrast (ClutterBrightnessContrastEffect *effect,
|
||||
gfloat *red,
|
||||
gfloat *green,
|
||||
gfloat *blue)
|
||||
{
|
||||
ClutterBrightnessContrastEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
priv = clutter_brightness_contrast_effect_get_instance_private (effect);
|
||||
if (red != NULL)
|
||||
*red = priv->contrast_red;
|
||||
|
||||
if (green != NULL)
|
||||
*green = priv->contrast_green;
|
||||
|
||||
if (blue != NULL)
|
||||
*blue = priv->contrast_blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_brightness_contrast_effect_set_contrast:
|
||||
* @effect: a #ClutterBrightnessContrastEffect
|
||||
* @contrast: contrast change for all three channels
|
||||
*
|
||||
* The range for @contrast is [-1.0, 1.0], where 0.0 designates no change;
|
||||
* a value below 0.0 indicates a decrease in contrast; and a value above
|
||||
* 0.0 indicates an increase.
|
||||
*/
|
||||
void
|
||||
clutter_brightness_contrast_effect_set_contrast (ClutterBrightnessContrastEffect *effect,
|
||||
gfloat contrast)
|
||||
{
|
||||
clutter_brightness_contrast_effect_set_contrast_full (effect,
|
||||
contrast,
|
||||
contrast,
|
||||
contrast);
|
||||
}
|
84
mutter/clutter/clutter/clutter-brightness-contrast-effect.h
Normal file
84
mutter/clutter/clutter/clutter-brightness-contrast-effect.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010-2012 Inclusive Design Research Centre, OCAD University.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Joseph Scheuhammer <clown@alum.mit.edu>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-color.h"
|
||||
#include "clutter/clutter-effect.h"
|
||||
#include "clutter/clutter-offscreen-effect.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BRIGHTNESS_CONTRAST_EFFECT (clutter_brightness_contrast_effect_get_type ())
|
||||
|
||||
|
||||
struct _ClutterBrightnessContrastEffectClass
|
||||
{
|
||||
ClutterOffscreenEffectClass parent_class;
|
||||
|
||||
CoglPipeline *base_pipeline;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterBrightnessContrastEffect,
|
||||
clutter_brightness_contrast_effect,
|
||||
CLUTTER, BRIGHTNESS_CONTRAST_EFFECT,
|
||||
ClutterOffscreenEffect)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterEffect * clutter_brightness_contrast_effect_new (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContrastEffect *effect,
|
||||
float red,
|
||||
float green,
|
||||
float blue);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_brightness_contrast_effect_set_brightness (ClutterBrightnessContrastEffect *effect,
|
||||
float brightness);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_brightness_contrast_effect_get_brightness (ClutterBrightnessContrastEffect *effect,
|
||||
float *red,
|
||||
float *green,
|
||||
float *blue);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastEffect *effect,
|
||||
float red,
|
||||
float green,
|
||||
float blue);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_brightness_contrast_effect_set_contrast (ClutterBrightnessContrastEffect *effect,
|
||||
float contrast);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_brightness_contrast_effect_get_contrast (ClutterBrightnessContrastEffect *effect,
|
||||
float *red,
|
||||
float *green,
|
||||
float *blue);
|
||||
|
||||
G_END_DECLS
|
785
mutter/clutter/clutter/clutter-click-action.c
Normal file
785
mutter/clutter/clutter/clutter-click-action.c
Normal file
@ -0,0 +1,785 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterClickAction:
|
||||
*
|
||||
* Action for clickable actors
|
||||
*
|
||||
* #ClutterClickAction is a sub-class of [class@Action] that implements
|
||||
* the logic for clickable actors, by using the low level events of
|
||||
* [class@Actor], such as [signal@Actor::button-press-event] and
|
||||
* [signal@Actor::button-release-event], to synthesize the high level
|
||||
* [signal@ClickAction::clicked] signal.
|
||||
*
|
||||
* To use #ClutterClickAction you just need to apply it to a [class@Actor]
|
||||
* using [method@Actor.add_action] and connect to the
|
||||
* [signal@ClickAction::clicked] signal:
|
||||
*
|
||||
* ```c
|
||||
* ClutterAction *action = clutter_click_action_new ();
|
||||
*
|
||||
* clutter_actor_add_action (actor, action);
|
||||
*
|
||||
* g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL);
|
||||
* ```
|
||||
*
|
||||
* #ClutterClickAction also supports long press gestures: a long press is
|
||||
* activated if the pointer remains pressed within a certain threshold (as
|
||||
* defined by the [property@ClickAction:long-press-threshold] property) for a
|
||||
* minimum amount of time (as the defined by the
|
||||
* [property@ClickAction:long-press-duration] property).
|
||||
* The [signal@ClickAction::long-press] signal is emitted multiple times,
|
||||
* using different [enum@LongPressState] values; to handle long presses
|
||||
* you should connect to the [signal@ClickAction::long-press] signal and
|
||||
* handle the different states:
|
||||
*
|
||||
* ```c
|
||||
* static gboolean
|
||||
* on_long_press (ClutterClickAction *action,
|
||||
* ClutterActor *actor,
|
||||
* ClutterLongPressState state)
|
||||
* {
|
||||
* switch (state)
|
||||
* {
|
||||
* case CLUTTER_LONG_PRESS_QUERY:
|
||||
* // return TRUE if the actor should support long press
|
||||
* // gestures, and FALSE otherwise; this state will be
|
||||
* // emitted on button presses
|
||||
* return TRUE;
|
||||
*
|
||||
* case CLUTTER_LONG_PRESS_ACTIVATE:
|
||||
* // this state is emitted if the minimum duration has
|
||||
* // been reached without the gesture being cancelled.
|
||||
* // the return value is not used
|
||||
* return TRUE;
|
||||
*
|
||||
* case CLUTTER_LONG_PRESS_CANCEL:
|
||||
* // this state is emitted if the long press was cancelled;
|
||||
* // for instance, the pointer went outside the actor or the
|
||||
* // allowed threshold, or the button was released before
|
||||
* // the minimum duration was reached. the return value is
|
||||
* // not used
|
||||
* return FALSE;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-click-action.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-marshal.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
struct _ClutterClickActionPrivate
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
guint long_press_id;
|
||||
|
||||
gint long_press_threshold;
|
||||
gint long_press_duration;
|
||||
gint drag_threshold;
|
||||
|
||||
guint press_button;
|
||||
ClutterInputDevice *press_device;
|
||||
ClutterEventSequence *press_sequence;
|
||||
ClutterModifierType modifier_state;
|
||||
gfloat press_x;
|
||||
gfloat press_y;
|
||||
|
||||
guint is_held : 1;
|
||||
guint is_pressed : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_HELD,
|
||||
PROP_PRESSED,
|
||||
PROP_LONG_PRESS_THRESHOLD,
|
||||
PROP_LONG_PRESS_DURATION,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
|
||||
|
||||
enum
|
||||
{
|
||||
CLICKED,
|
||||
LONG_PRESS,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint click_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterClickAction, clutter_click_action, CLUTTER_TYPE_ACTION)
|
||||
|
||||
static inline void
|
||||
click_action_set_pressed (ClutterClickAction *action,
|
||||
gboolean is_pressed)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (action);
|
||||
|
||||
is_pressed = !!is_pressed;
|
||||
|
||||
if (priv->is_pressed == is_pressed)
|
||||
return;
|
||||
|
||||
priv->is_pressed = is_pressed;
|
||||
g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_PRESSED]);
|
||||
}
|
||||
|
||||
static inline void
|
||||
click_action_set_held (ClutterClickAction *action,
|
||||
gboolean is_held)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (action);
|
||||
|
||||
is_held = !!is_held;
|
||||
|
||||
if (priv->is_held == is_held)
|
||||
return;
|
||||
|
||||
priv->is_held = is_held;
|
||||
g_object_notify_by_pspec (G_OBJECT (action), obj_props[PROP_HELD]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
click_action_emit_long_press (gpointer data)
|
||||
{
|
||||
ClutterClickAction *action = data;
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (action);
|
||||
ClutterActor *actor;
|
||||
gboolean result;
|
||||
|
||||
priv->long_press_id = 0;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (data);
|
||||
|
||||
g_signal_emit (action, click_signals[LONG_PRESS], 0,
|
||||
actor,
|
||||
CLUTTER_LONG_PRESS_ACTIVATE,
|
||||
&result);
|
||||
|
||||
click_action_set_pressed (action, FALSE);
|
||||
click_action_set_held (action, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
click_action_query_long_press (ClutterClickAction *action)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (action);
|
||||
ClutterActor *actor;
|
||||
gboolean result = FALSE;
|
||||
gint timeout;
|
||||
|
||||
if (priv->long_press_duration < 0)
|
||||
{
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
|
||||
g_object_get (settings,
|
||||
"long-press-duration", &timeout,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
timeout = priv->long_press_duration;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||
|
||||
g_signal_emit (action, click_signals[LONG_PRESS], 0,
|
||||
actor,
|
||||
CLUTTER_LONG_PRESS_QUERY,
|
||||
&result);
|
||||
|
||||
if (result)
|
||||
{
|
||||
g_clear_handle_id (&priv->long_press_id, g_source_remove);
|
||||
priv->long_press_id =
|
||||
clutter_threads_add_timeout (timeout,
|
||||
click_action_emit_long_press,
|
||||
action);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
click_action_cancel_long_press (ClutterClickAction *action)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (action);
|
||||
|
||||
if (priv->long_press_id != 0)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
gboolean result;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||
|
||||
g_clear_handle_id (&priv->long_press_id, g_source_remove);
|
||||
|
||||
g_signal_emit (action, click_signals[LONG_PRESS], 0,
|
||||
actor,
|
||||
CLUTTER_LONG_PRESS_CANCEL,
|
||||
&result);
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
event_within_drag_threshold (ClutterClickAction *click_action,
|
||||
const 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
|
||||
clutter_click_action_handle_event (ClutterAction *action,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterClickAction *click_action = CLUTTER_CLICK_ACTION (action);
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (click_action);
|
||||
ClutterActor *actor =
|
||||
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||
gboolean has_button = TRUE;
|
||||
ClutterModifierType modifier_state;
|
||||
ClutterActor *target;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
if (priv->press_sequence != NULL &&
|
||||
clutter_event_get_event_sequence (event) != priv->press_sequence)
|
||||
{
|
||||
click_action_set_held (click_action, FALSE);
|
||||
click_action_cancel_long_press (click_action);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
switch (clutter_event_type (event))
|
||||
{
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
has_button = FALSE;
|
||||
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
if (priv->is_held)
|
||||
return CLUTTER_EVENT_STOP;
|
||||
|
||||
target = clutter_stage_get_device_actor (CLUTTER_STAGE (clutter_actor_get_stage (actor)),
|
||||
clutter_event_get_device (event),
|
||||
clutter_event_get_event_sequence (event));
|
||||
|
||||
if (!clutter_actor_contains (actor, target))
|
||||
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_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);
|
||||
|
||||
if (priv->long_press_threshold < 0)
|
||||
{
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
|
||||
g_object_get (settings,
|
||||
"dnd-drag-threshold", &priv->drag_threshold,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
priv->drag_threshold = priv->long_press_threshold;
|
||||
|
||||
if (priv->stage == NULL)
|
||||
priv->stage = clutter_actor_get_stage (actor);
|
||||
|
||||
click_action_set_pressed (click_action, TRUE);
|
||||
click_action_set_held (click_action, TRUE);
|
||||
click_action_query_long_press (click_action);
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
click_action_set_pressed (click_action, priv->is_held);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
case CLUTTER_LEAVE:
|
||||
click_action_set_pressed (click_action, FALSE);
|
||||
click_action_cancel_long_press (click_action);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
clutter_click_action_release (click_action);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_END:
|
||||
has_button = FALSE;
|
||||
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (!priv->is_held)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
if ((has_button && clutter_event_get_button (event) != priv->press_button) ||
|
||||
clutter_event_get_device (event) != priv->press_device ||
|
||||
clutter_event_get_event_sequence (event) != priv->press_sequence)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
click_action_set_held (click_action, FALSE);
|
||||
click_action_cancel_long_press (click_action);
|
||||
|
||||
g_clear_handle_id (&priv->long_press_id, g_source_remove);
|
||||
|
||||
target = clutter_stage_get_device_actor (CLUTTER_STAGE (clutter_actor_get_stage (actor)),
|
||||
clutter_event_get_device (event),
|
||||
clutter_event_get_event_sequence (event));
|
||||
|
||||
if (!clutter_actor_contains (actor, target))
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
/* exclude any button-mask so that we can compare
|
||||
* the press and release states properly */
|
||||
modifier_state = clutter_event_get_state (event) &
|
||||
~(CLUTTER_BUTTON1_MASK |
|
||||
CLUTTER_BUTTON2_MASK |
|
||||
CLUTTER_BUTTON3_MASK |
|
||||
CLUTTER_BUTTON4_MASK |
|
||||
CLUTTER_BUTTON5_MASK);
|
||||
|
||||
/* if press and release states don't match we
|
||||
* simply ignore modifier keys. i.e. modifier keys
|
||||
* are expected to be pressed throughout the whole
|
||||
* click */
|
||||
if (modifier_state != priv->modifier_state)
|
||||
priv->modifier_state = 0;
|
||||
|
||||
click_action_set_pressed (click_action, FALSE);
|
||||
|
||||
if (event_within_drag_threshold (click_action, event))
|
||||
g_signal_emit (click_action, click_signals[CLICKED], 0, actor);
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
{
|
||||
if (clutter_event_get_device (event) != priv->press_device ||
|
||||
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 (click_action, event))
|
||||
clutter_click_action_release (click_action);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return priv->is_held ? CLUTTER_EVENT_STOP : CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_sequence_cancelled (ClutterAction *action,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
ClutterClickAction *self = CLUTTER_CLICK_ACTION (action);
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (self);
|
||||
|
||||
if (priv->press_device == device && priv->press_sequence == sequence)
|
||||
clutter_click_action_release (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta);
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (action);
|
||||
|
||||
g_clear_handle_id (&priv->long_press_id, g_source_remove);
|
||||
|
||||
click_action_set_pressed (action, FALSE);
|
||||
click_action_set_held (action, FALSE);
|
||||
|
||||
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_set_enabled (ClutterActorMeta *meta,
|
||||
gboolean is_enabled)
|
||||
{
|
||||
ClutterClickAction *click_action = CLUTTER_CLICK_ACTION (meta);
|
||||
ClutterActorMetaClass *parent_class =
|
||||
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class);
|
||||
|
||||
if (!is_enabled)
|
||||
clutter_click_action_release (click_action);
|
||||
|
||||
parent_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LONG_PRESS_DURATION:
|
||||
priv->long_press_duration = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_LONG_PRESS_THRESHOLD:
|
||||
priv->long_press_threshold = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HELD:
|
||||
g_value_set_boolean (value, priv->is_held);
|
||||
break;
|
||||
|
||||
case PROP_PRESSED:
|
||||
g_value_set_boolean (value, priv->is_pressed);
|
||||
break;
|
||||
|
||||
case PROP_LONG_PRESS_DURATION:
|
||||
g_value_set_int (value, priv->long_press_duration);
|
||||
break;
|
||||
|
||||
case PROP_LONG_PRESS_THRESHOLD:
|
||||
g_value_set_int (value, priv->long_press_threshold);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
|
||||
|
||||
g_clear_handle_id (&priv->long_press_id, g_source_remove);
|
||||
|
||||
G_OBJECT_CLASS (clutter_click_action_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_class_init (ClutterClickActionClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
ClutterActionClass *action_class = CLUTTER_ACTION_CLASS (klass);
|
||||
|
||||
action_class->handle_event = clutter_click_action_handle_event;
|
||||
action_class->sequence_cancelled = clutter_click_action_sequence_cancelled;
|
||||
|
||||
meta_class->set_actor = clutter_click_action_set_actor;
|
||||
meta_class->set_enabled = clutter_click_action_set_enabled;
|
||||
|
||||
gobject_class->dispose = clutter_click_action_dispose;
|
||||
gobject_class->set_property = clutter_click_action_set_property;
|
||||
gobject_class->get_property = clutter_click_action_get_property;
|
||||
|
||||
/**
|
||||
* ClutterClickAction:pressed:
|
||||
*
|
||||
* Whether the clickable actor should be in "pressed" state
|
||||
*/
|
||||
obj_props[PROP_PRESSED] =
|
||||
g_param_spec_boolean ("pressed", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterClickAction:held:
|
||||
*
|
||||
* Whether the clickable actor has the pointer grabbed
|
||||
*/
|
||||
obj_props[PROP_HELD] =
|
||||
g_param_spec_boolean ("held", NULL, NULL,
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterClickAction:long-press-duration:
|
||||
*
|
||||
* The minimum duration of a press for it to be recognized as a long
|
||||
* press gesture, in milliseconds.
|
||||
*
|
||||
* A value of -1 will make the #ClutterClickAction use the value of
|
||||
* the [property@Settings:long-press-duration] property.
|
||||
*/
|
||||
obj_props[PROP_LONG_PRESS_DURATION] =
|
||||
g_param_spec_int ("long-press-duration", NULL, NULL,
|
||||
-1, G_MAXINT,
|
||||
-1,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterClickAction:long-press-threshold:
|
||||
*
|
||||
* The maximum allowed distance that can be covered (on both axes) before
|
||||
* a long press gesture is cancelled, in pixels.
|
||||
*
|
||||
* A value of -1 will make the #ClutterClickAction use the value of
|
||||
* the [property@Settings:dnd-drag-threshold] property.
|
||||
*/
|
||||
obj_props[PROP_LONG_PRESS_THRESHOLD] =
|
||||
g_param_spec_int ("long-press-threshold", NULL, NULL,
|
||||
-1, G_MAXINT,
|
||||
-1,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class,
|
||||
PROP_LAST,
|
||||
obj_props);
|
||||
|
||||
/**
|
||||
* ClutterClickAction::clicked:
|
||||
* @action: the #ClutterClickAction that emitted the signal
|
||||
* @actor: the #ClutterActor attached to the @action
|
||||
*
|
||||
* The signal is emitted when the [class@Actor] to which
|
||||
* a #ClutterClickAction has been applied should respond to a
|
||||
* pointer button press and release events
|
||||
*/
|
||||
click_signals[CLICKED] =
|
||||
g_signal_new (I_("clicked"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterClickActionClass, clicked),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
|
||||
/**
|
||||
* ClutterClickAction::long-press:
|
||||
* @action: the #ClutterClickAction that emitted the signal
|
||||
* @actor: the #ClutterActor attached to the @action
|
||||
* @state: the long press state
|
||||
*
|
||||
* The signal is emitted during the long press gesture
|
||||
* handling.
|
||||
*
|
||||
* This signal can be emitted multiple times with different states.
|
||||
*
|
||||
* The %CLUTTER_LONG_PRESS_QUERY state will be emitted on button presses,
|
||||
* and its return value will determine whether the long press handling
|
||||
* should be initiated. If the signal handlers will return %TRUE, the
|
||||
* %CLUTTER_LONG_PRESS_QUERY state will be followed either by a signal
|
||||
* emission with the %CLUTTER_LONG_PRESS_ACTIVATE state if the long press
|
||||
* constraints were respected, or by a signal emission with the
|
||||
* %CLUTTER_LONG_PRESS_CANCEL state if the long press was cancelled.
|
||||
*
|
||||
* It is possible to forcibly cancel a long press detection using
|
||||
* [method@ClickAction.release].
|
||||
*
|
||||
* Return value: Only the %CLUTTER_LONG_PRESS_QUERY state uses the
|
||||
* returned value of the handler; other states will ignore it
|
||||
*/
|
||||
click_signals[LONG_PRESS] =
|
||||
g_signal_new (I_("long-press"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterClickActionClass, long_press),
|
||||
NULL, NULL,
|
||||
_clutter_marshal_BOOLEAN__OBJECT_ENUM,
|
||||
G_TYPE_BOOLEAN, 2,
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
CLUTTER_TYPE_LONG_PRESS_STATE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_click_action_init (ClutterClickAction *self)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (self);
|
||||
|
||||
priv->long_press_threshold = -1;
|
||||
priv->long_press_duration = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_click_action_new:
|
||||
*
|
||||
* Creates a new #ClutterClickAction instance
|
||||
*
|
||||
* Return value: the newly created #ClutterClickAction
|
||||
*/
|
||||
ClutterAction *
|
||||
clutter_click_action_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_CLICK_ACTION, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_click_action_release:
|
||||
* @action: a #ClutterClickAction
|
||||
*
|
||||
* Emulates a release of the pointer button, which ungrabs the pointer
|
||||
* and unsets the [property@ClickAction:pressed] state.
|
||||
*
|
||||
* This function will also cancel the long press gesture if one was
|
||||
* initiated.
|
||||
*
|
||||
* This function is useful to break a grab, for instance after a certain
|
||||
* amount of time has passed.
|
||||
*/
|
||||
void
|
||||
clutter_click_action_release (ClutterClickAction *action)
|
||||
{
|
||||
ClutterClickActionPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CLICK_ACTION (action));
|
||||
|
||||
priv = clutter_click_action_get_instance_private (action);
|
||||
|
||||
if (!priv->is_held)
|
||||
return;
|
||||
|
||||
click_action_cancel_long_press (action);
|
||||
click_action_set_held (action, FALSE);
|
||||
click_action_set_pressed (action, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_click_action_get_button:
|
||||
* @action: a #ClutterClickAction
|
||||
*
|
||||
* Retrieves the button that was pressed.
|
||||
*
|
||||
* Return value: the button value
|
||||
*/
|
||||
guint
|
||||
clutter_click_action_get_button (ClutterClickAction *action)
|
||||
{
|
||||
ClutterClickActionPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
|
||||
|
||||
priv = clutter_click_action_get_instance_private (action);
|
||||
|
||||
return priv->press_button;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_click_action_get_state:
|
||||
* @action: a #ClutterClickAction
|
||||
*
|
||||
* Retrieves the modifier state of the click action.
|
||||
*
|
||||
* Return value: the modifier state parameter, or 0
|
||||
*/
|
||||
ClutterModifierType
|
||||
clutter_click_action_get_state (ClutterClickAction *action)
|
||||
{
|
||||
ClutterClickActionPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
|
||||
|
||||
priv = clutter_click_action_get_instance_private (action);
|
||||
|
||||
return priv->modifier_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_click_action_get_coords:
|
||||
* @action: a #ClutterClickAction
|
||||
* @press_x: (out): return location for the X coordinate, or %NULL
|
||||
* @press_y: (out): return location for the Y coordinate, or %NULL
|
||||
*
|
||||
* Retrieves the screen coordinates of the button press.
|
||||
*/
|
||||
void
|
||||
clutter_click_action_get_coords (ClutterClickAction *action,
|
||||
gfloat *press_x,
|
||||
gfloat *press_y)
|
||||
{
|
||||
ClutterClickActionPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTION (action));
|
||||
|
||||
priv = clutter_click_action_get_instance_private (action);
|
||||
|
||||
if (press_x != NULL)
|
||||
*press_x = priv->press_x;
|
||||
|
||||
if (press_y != NULL)
|
||||
*press_y = priv->press_y;
|
||||
}
|
84
mutter/clutter/clutter/clutter-click-action.h
Normal file
84
mutter/clutter/clutter/clutter-click-action.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Inspired by the StClickable class in GNOME Shell, written by:
|
||||
* Colin Walters <walters@verbum.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-action.h"
|
||||
#include "clutter/clutter-event.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_CLICK_ACTION (clutter_click_action_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterClickAction, clutter_click_action,
|
||||
CLUTTER, CLICK_ACTION, ClutterAction);
|
||||
|
||||
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
|
||||
|
||||
/**
|
||||
* ClutterClickActionClass:
|
||||
* @clicked: class handler for the #ClutterClickAction::clicked signal
|
||||
* @long_press: class handler for the #ClutterClickAction::long-press signal
|
||||
*
|
||||
* The #ClutterClickActionClass structure
|
||||
* contains only private data
|
||||
*/
|
||||
struct _ClutterClickActionClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActionClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (* clicked) (ClutterClickAction *action,
|
||||
ClutterActor *actor);
|
||||
|
||||
gboolean (* long_press) (ClutterClickAction *action,
|
||||
ClutterActor *actor,
|
||||
ClutterLongPressState state);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterAction * clutter_click_action_new (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_click_action_get_button (ClutterClickAction *action);
|
||||
CLUTTER_EXPORT
|
||||
ClutterModifierType clutter_click_action_get_state (ClutterClickAction *action);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_click_action_get_coords (ClutterClickAction *action,
|
||||
gfloat *press_x,
|
||||
gfloat *press_y);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_click_action_release (ClutterClickAction *action);
|
||||
|
||||
G_END_DECLS
|
465
mutter/clutter/clutter/clutter-clone.c
Normal file
465
mutter/clutter/clutter/clutter-clone.c
Normal file
@ -0,0 +1,465 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation.
|
||||
*
|
||||
* Authored By: Robert Bragg <robert@linux.intel.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterClone:
|
||||
*
|
||||
* An actor that displays a clone of a source actor
|
||||
*
|
||||
* #ClutterClone is a [class@Clutter.Actor] which draws with the paint
|
||||
* function of another actor, scaled to fit its own allocation.
|
||||
*
|
||||
* #ClutterClone can be used to efficiently clone any other actor.
|
||||
*
|
||||
* #ClutterClone does not require the presence of support for FBOs
|
||||
* in the underlying GL or GLES implementation.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#include "clutter/clutter-clone.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-main.h"
|
||||
#include "clutter/clutter-paint-volume-private.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
typedef struct _ClutterClonePrivate
|
||||
{
|
||||
ClutterActor *clone_source;
|
||||
float x_scale, y_scale;
|
||||
|
||||
gulong source_destroy_id;
|
||||
} ClutterClonePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterClone, clutter_clone, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_SOURCE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
static void clutter_clone_set_source_internal (ClutterClone *clone,
|
||||
ClutterActor *source);
|
||||
static void
|
||||
clutter_clone_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterClonePrivate *priv =
|
||||
clutter_clone_get_instance_private (CLUTTER_CLONE (self));
|
||||
ClutterActor *clone_source = priv->clone_source;
|
||||
|
||||
if (clone_source == NULL)
|
||||
{
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = 0;
|
||||
}
|
||||
else
|
||||
clutter_actor_get_preferred_width (clone_source,
|
||||
for_height,
|
||||
min_width_p,
|
||||
natural_width_p);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_get_preferred_height (ClutterActor *self,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterClonePrivate *priv =
|
||||
clutter_clone_get_instance_private (CLUTTER_CLONE (self));
|
||||
ClutterActor *clone_source = priv->clone_source;
|
||||
|
||||
if (clone_source == NULL)
|
||||
{
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = 0;
|
||||
}
|
||||
else
|
||||
clutter_actor_get_preferred_height (clone_source,
|
||||
for_width,
|
||||
min_height_p,
|
||||
natural_height_p);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_paint (ClutterActor *actor,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterClone *self = CLUTTER_CLONE (actor);
|
||||
ClutterClonePrivate *priv = clutter_clone_get_instance_private (self);
|
||||
gboolean was_unmapped = FALSE;
|
||||
|
||||
if (priv->clone_source == NULL)
|
||||
return;
|
||||
|
||||
CLUTTER_NOTE (PAINT, "painting clone actor '%s'",
|
||||
_clutter_actor_get_debug_name (actor));
|
||||
|
||||
/* The final bits of magic:
|
||||
* - We need to override the paint opacity of the actor with our own
|
||||
* opacity.
|
||||
* - We need to inform the actor that it's in a clone paint (for the function
|
||||
* clutter_actor_is_in_clone_paint())
|
||||
* - We need to stop clutter_actor_paint applying the model view matrix of
|
||||
* the clone source actor.
|
||||
*/
|
||||
_clutter_actor_set_in_clone_paint (priv->clone_source, TRUE);
|
||||
clutter_actor_set_opacity_override (priv->clone_source,
|
||||
clutter_actor_get_paint_opacity (actor));
|
||||
_clutter_actor_set_enable_model_view_transform (priv->clone_source, FALSE);
|
||||
|
||||
if (!clutter_actor_is_mapped (priv->clone_source))
|
||||
{
|
||||
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, TRUE);
|
||||
was_unmapped = TRUE;
|
||||
}
|
||||
|
||||
/* If the source isn't ultimately parented to a toplevel, it can't be
|
||||
* realized or painted.
|
||||
*/
|
||||
if (clutter_actor_is_realized (priv->clone_source))
|
||||
{
|
||||
CoglFramebuffer *fb = NULL;
|
||||
|
||||
if (priv->x_scale != 1.0 || priv->y_scale != 1.0)
|
||||
{
|
||||
fb = clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
cogl_framebuffer_push_matrix (fb);
|
||||
cogl_framebuffer_scale (fb, priv->x_scale, priv->y_scale, 1.0f);
|
||||
}
|
||||
|
||||
_clutter_actor_push_clone_paint ();
|
||||
clutter_actor_paint (priv->clone_source, paint_context);
|
||||
_clutter_actor_pop_clone_paint ();
|
||||
|
||||
if (fb != NULL)
|
||||
cogl_framebuffer_pop_matrix (fb);
|
||||
}
|
||||
|
||||
if (was_unmapped)
|
||||
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, FALSE);
|
||||
|
||||
_clutter_actor_set_enable_model_view_transform (priv->clone_source, TRUE);
|
||||
clutter_actor_set_opacity_override (priv->clone_source, -1);
|
||||
_clutter_actor_set_in_clone_paint (priv->clone_source, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clone_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
ClutterClonePrivate *priv =
|
||||
clutter_clone_get_instance_private (CLUTTER_CLONE (actor));
|
||||
const ClutterPaintVolume *source_volume;
|
||||
|
||||
/* if the source is not set the paint volume is defined to be empty */
|
||||
if (priv->clone_source == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* query the volume of the source actor and simply masquerade it as
|
||||
* the clones volume... */
|
||||
source_volume = clutter_actor_get_paint_volume (priv->clone_source);
|
||||
if (source_volume == NULL)
|
||||
return FALSE;
|
||||
|
||||
_clutter_paint_volume_set_from_volume (volume, source_volume);
|
||||
_clutter_paint_volume_set_reference_actor (volume, actor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clone_has_overlaps (ClutterActor *actor)
|
||||
{
|
||||
ClutterClonePrivate *priv =
|
||||
clutter_clone_get_instance_private (CLUTTER_CLONE (actor));
|
||||
|
||||
/* The clone has overlaps iff the source has overlaps */
|
||||
|
||||
if (priv->clone_source == NULL)
|
||||
return FALSE;
|
||||
|
||||
return clutter_actor_has_overlaps (priv->clone_source);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box)
|
||||
{
|
||||
ClutterClonePrivate *priv =
|
||||
clutter_clone_get_instance_private (CLUTTER_CLONE (self));
|
||||
ClutterActorClass *parent_class;
|
||||
ClutterActorBox source_box;
|
||||
float x_scale, y_scale;
|
||||
|
||||
/* chain up */
|
||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
|
||||
parent_class->allocate (self, box);
|
||||
|
||||
if (priv->clone_source == NULL)
|
||||
return;
|
||||
|
||||
/* ClutterActor delays allocating until the actor is shown; however
|
||||
* we cannot paint it correctly in that case, so force an allocation.
|
||||
*/
|
||||
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
|
||||
!clutter_actor_has_allocation (priv->clone_source))
|
||||
{
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
clutter_actor_get_fixed_position (priv->clone_source, &x, &y);
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source, x, y);
|
||||
}
|
||||
|
||||
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
|
||||
|
||||
/* We need to scale what the clone-source actor paints to fill our own
|
||||
* allocation...
|
||||
*/
|
||||
x_scale = clutter_actor_box_get_width (box)
|
||||
/ clutter_actor_box_get_width (&source_box);
|
||||
y_scale = clutter_actor_box_get_height (box)
|
||||
/ clutter_actor_box_get_height (&source_box);
|
||||
|
||||
if (!G_APPROX_VALUE (priv->x_scale, x_scale, FLT_EPSILON) ||
|
||||
!G_APPROX_VALUE (priv->y_scale, y_scale, FLT_EPSILON))
|
||||
{
|
||||
priv->x_scale = x_scale;
|
||||
priv->y_scale = y_scale;
|
||||
clutter_actor_queue_redraw (self);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* XXX - this is wrong: ClutterClone cannot clone unparented
|
||||
* actors, as it will break all invariants
|
||||
*/
|
||||
|
||||
/* we act like a "foster parent" for the source we are cloning;
|
||||
* if the source has not been parented we have to force an
|
||||
* allocation on it, so that we can paint it correctly from
|
||||
* within our paint() implementation. since the actor does not
|
||||
* have a parent, and thus it won't be painted by the usual
|
||||
* paint cycle, we can safely give it as much size as it requires
|
||||
*/
|
||||
if (clutter_actor_get_parent (priv->clone_source) == NULL)
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterClone *self = CLUTTER_CLONE (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
clutter_clone_set_source (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterClonePrivate *priv =
|
||||
clutter_clone_get_instance_private (CLUTTER_CLONE (gobject));
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SOURCE:
|
||||
g_value_set_object (value, priv->clone_source);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_dispose (GObject *gobject)
|
||||
{
|
||||
clutter_clone_set_source_internal (CLUTTER_CLONE (gobject), NULL);
|
||||
|
||||
G_OBJECT_CLASS (clutter_clone_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_class_init (ClutterCloneClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->paint = clutter_clone_paint;
|
||||
actor_class->get_paint_volume = clutter_clone_get_paint_volume;
|
||||
actor_class->get_preferred_width = clutter_clone_get_preferred_width;
|
||||
actor_class->get_preferred_height = clutter_clone_get_preferred_height;
|
||||
actor_class->allocate = clutter_clone_allocate;
|
||||
actor_class->has_overlaps = clutter_clone_has_overlaps;
|
||||
|
||||
gobject_class->dispose = clutter_clone_dispose;
|
||||
gobject_class->set_property = clutter_clone_set_property;
|
||||
gobject_class->get_property = clutter_clone_get_property;
|
||||
|
||||
/**
|
||||
* ClutterClone:source:
|
||||
*
|
||||
* This property specifies the source actor being cloned.
|
||||
*/
|
||||
obj_props[PROP_SOURCE] =
|
||||
g_param_spec_object ("source", NULL, NULL,
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_init (ClutterClone *self)
|
||||
{
|
||||
ClutterClonePrivate *priv = clutter_clone_get_instance_private (self);
|
||||
|
||||
priv->x_scale = 1.f;
|
||||
priv->y_scale = 1.f;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_clone_new:
|
||||
* @source: a #ClutterActor, or %NULL
|
||||
*
|
||||
* Creates a new #ClutterActor which clones @source/
|
||||
*
|
||||
* Return value: the newly created #ClutterClone
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_clone_new (ClutterActor *source)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_CLONE, "source", source, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_source_destroyed (ClutterActor *source,
|
||||
ClutterClone *self)
|
||||
{
|
||||
clutter_clone_set_source_internal (self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_set_source_internal (ClutterClone *self,
|
||||
ClutterActor *source)
|
||||
{
|
||||
ClutterClonePrivate *priv = clutter_clone_get_instance_private (self);
|
||||
|
||||
if (priv->clone_source == source)
|
||||
return;
|
||||
|
||||
if (priv->clone_source != NULL)
|
||||
{
|
||||
g_clear_signal_handler (&priv->source_destroy_id, priv->clone_source);
|
||||
_clutter_actor_detach_clone (priv->clone_source, CLUTTER_ACTOR (self));
|
||||
g_object_unref (priv->clone_source);
|
||||
priv->clone_source = NULL;
|
||||
}
|
||||
|
||||
if (source != NULL)
|
||||
{
|
||||
priv->clone_source = g_object_ref (source);
|
||||
_clutter_actor_attach_clone (priv->clone_source, CLUTTER_ACTOR (self));
|
||||
priv->source_destroy_id = g_signal_connect (priv->clone_source, "destroy",
|
||||
G_CALLBACK (on_source_destroyed), self);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_SOURCE]);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_clone_set_source:
|
||||
* @self: a #ClutterClone
|
||||
* @source: (allow-none): a #ClutterActor, or %NULL
|
||||
*
|
||||
* Sets @source as the source actor to be cloned by @self.
|
||||
*/
|
||||
void
|
||||
clutter_clone_set_source (ClutterClone *self,
|
||||
ClutterActor *source)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_CLONE (self));
|
||||
g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source));
|
||||
|
||||
clutter_clone_set_source_internal (self, source);
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_clone_get_source:
|
||||
* @self: a #ClutterClone
|
||||
*
|
||||
* Retrieves the source #ClutterActor being cloned by @self.
|
||||
*
|
||||
* Return value: (transfer none): the actor source for the clone
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_clone_get_source (ClutterClone *self)
|
||||
{
|
||||
ClutterClonePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_CLONE (self), NULL);
|
||||
|
||||
priv = clutter_clone_get_instance_private (self);
|
||||
return priv->clone_source;
|
||||
}
|
61
mutter/clutter/clutter/clutter-clone.h
Normal file
61
mutter/clutter/clutter/clutter-clone.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2008 Intel Corporation.
|
||||
*
|
||||
* Authored By: Robert Bragg <robert@linux.intel.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-actor.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_CLONE (clutter_clone_get_type ())
|
||||
|
||||
/**
|
||||
* ClutterCloneClass:
|
||||
*
|
||||
* The #ClutterCloneClass structure contains only private data
|
||||
*/
|
||||
struct _ClutterCloneClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterClone,
|
||||
clutter_clone,
|
||||
CLUTTER, CLONE,
|
||||
ClutterActor)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_clone_new (ClutterActor *source);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_clone_set_source (ClutterClone *self,
|
||||
ClutterActor *source);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_clone_get_source (ClutterClone *self);
|
||||
|
||||
G_END_DECLS
|
181
mutter/clutter/clutter/clutter-color-state.c
Normal file
181
mutter/clutter/clutter/clutter-color-state.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Naveen Kumar <naveen1.kumar@intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterColorState:
|
||||
*
|
||||
* Color state of each ClutterActor
|
||||
*
|
||||
* The #ClutterColorState class contains the colorspace of each color
|
||||
* states (e.g. sRGB colorspace).
|
||||
*
|
||||
* Each [class@Actor] would own such an object.
|
||||
*
|
||||
* A single #ClutterColorState object can be shared by multiple [class@Actor]
|
||||
* or maybe a separate color state for each [class@Actor] (depending on whether
|
||||
* #ClutterColorState would be statefull or stateless).
|
||||
*
|
||||
* #ClutterColorState, if not set during construction, it will default to sRGB
|
||||
* color state
|
||||
*
|
||||
* The #ClutterColorState would have API to get the colorspace, whether the
|
||||
* actor content is in pq or not, and things like that
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-color-state.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_COLORSPACE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[N_PROPS];
|
||||
|
||||
typedef struct _ClutterColorStatePrivate ClutterColorStatePrivate;
|
||||
|
||||
struct _ClutterColorState
|
||||
{
|
||||
GObject parent_instance;
|
||||
};
|
||||
|
||||
struct _ClutterColorStatePrivate
|
||||
{
|
||||
ClutterColorspace colorspace;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterColorState,
|
||||
clutter_color_state,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
ClutterColorspace
|
||||
clutter_color_state_get_colorspace (ClutterColorState *color_state)
|
||||
{
|
||||
ClutterColorStatePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_COLOR_STATE (color_state),
|
||||
CLUTTER_COLORSPACE_UNKNOWN);
|
||||
|
||||
priv = clutter_color_state_get_instance_private (color_state);
|
||||
|
||||
return priv->colorspace;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_color_state_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterColorState *color_state = CLUTTER_COLOR_STATE (object);
|
||||
ClutterColorStatePrivate *priv;
|
||||
|
||||
priv = clutter_color_state_get_instance_private (color_state);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLORSPACE:
|
||||
priv->colorspace = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_color_state_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterColorState *color_state = CLUTTER_COLOR_STATE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLORSPACE:
|
||||
g_value_set_enum (value,
|
||||
clutter_color_state_get_colorspace (color_state));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_color_state_class_init (ClutterColorStateClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = clutter_color_state_set_property;
|
||||
gobject_class->get_property = clutter_color_state_get_property;
|
||||
|
||||
/**
|
||||
* ClutterColorState:colorspace:
|
||||
*
|
||||
* Colorspace information of the each color state,
|
||||
* defaults to sRGB colorspace
|
||||
*/
|
||||
obj_props[PROP_COLORSPACE] =
|
||||
g_param_spec_enum ("colorspace", NULL, NULL,
|
||||
CLUTTER_TYPE_COLORSPACE,
|
||||
CLUTTER_COLORSPACE_SRGB,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_color_state_init (ClutterColorState *color_state)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_state_new:
|
||||
*
|
||||
* Create a new ClutterColorState object.
|
||||
*
|
||||
* Return value: A new ClutterColorState object.
|
||||
**/
|
||||
ClutterColorState*
|
||||
clutter_color_state_new (ClutterColorspace colorspace)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_COLOR_STATE,
|
||||
"colorspace", colorspace,
|
||||
NULL);
|
||||
}
|
47
mutter/clutter/clutter/clutter-color-state.h
Normal file
47
mutter/clutter/clutter/clutter-color-state.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2022 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Naveen Kumar <naveen1.kumar@intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_COLOR_STATE (clutter_color_state_get_type ())
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ClutterColorState, clutter_color_state,
|
||||
CLUTTER, COLOR_STATE,
|
||||
GObject)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterColorState * clutter_color_state_new (ClutterColorspace colorspace);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterColorspace clutter_color_state_get_colorspace (ClutterColorState *color_state);
|
||||
|
||||
G_END_DECLS
|
962
mutter/clutter/clutter/clutter-color.c
Normal file
962
mutter/clutter/clutter/clutter-color.c
Normal file
@ -0,0 +1,962 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <pango/pango-attributes.h>
|
||||
|
||||
#include "clutter/clutter-interval.h"
|
||||
#include "clutter/clutter-main.h"
|
||||
#include "clutter/clutter-color.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
|
||||
/**
|
||||
* clutter_color_to_hls:
|
||||
* @color: a #ClutterColor
|
||||
* @hue: (out): return location for the hue value or %NULL
|
||||
* @luminance: (out): return location for the luminance value or %NULL
|
||||
* @saturation: (out): return location for the saturation value or %NULL
|
||||
*
|
||||
* Converts @color to the HLS format.
|
||||
*
|
||||
* The @hue value is in the 0 .. 360 range. The @luminance and
|
||||
* @saturation values are in the 0 .. 1 range.
|
||||
*/
|
||||
void
|
||||
clutter_color_to_hls (const ClutterColor *color,
|
||||
float *hue,
|
||||
float *luminance,
|
||||
float *saturation)
|
||||
{
|
||||
float red, green, blue;
|
||||
float min, max, delta;
|
||||
float h, l, s;
|
||||
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
red = color->red / 255.0;
|
||||
green = color->green / 255.0;
|
||||
blue = color->blue / 255.0;
|
||||
|
||||
if (red > green)
|
||||
{
|
||||
if (red > blue)
|
||||
max = red;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
if (green < blue)
|
||||
min = green;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (green > blue)
|
||||
max = green;
|
||||
else
|
||||
max = blue;
|
||||
|
||||
if (red < blue)
|
||||
min = red;
|
||||
else
|
||||
min = blue;
|
||||
}
|
||||
|
||||
l = (max + min) / 2;
|
||||
s = 0;
|
||||
h = 0;
|
||||
|
||||
if (max != min)
|
||||
{
|
||||
if (l <= 0.5)
|
||||
s = (max - min) / (max + min);
|
||||
else
|
||||
s = (max - min) / (2.0 - max - min);
|
||||
|
||||
delta = max - min;
|
||||
|
||||
if (red == max)
|
||||
h = (green - blue) / delta;
|
||||
else if (green == max)
|
||||
h = 2.0 + (blue - red) / delta;
|
||||
else if (blue == max)
|
||||
h = 4.0 + (red - green) / delta;
|
||||
|
||||
h *= 60;
|
||||
|
||||
if (h < 0)
|
||||
h += 360.0;
|
||||
}
|
||||
|
||||
if (hue)
|
||||
*hue = h;
|
||||
|
||||
if (luminance)
|
||||
*luminance = l;
|
||||
|
||||
if (saturation)
|
||||
*saturation = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_from_hls:
|
||||
* @color: (out): return location for a #ClutterColor
|
||||
* @hue: hue value, in the 0 .. 360 range
|
||||
* @luminance: luminance value, in the 0 .. 1 range
|
||||
* @saturation: saturation value, in the 0 .. 1 range
|
||||
*
|
||||
* Converts a color expressed in HLS (hue, luminance and saturation)
|
||||
* values into a #ClutterColor.
|
||||
*/
|
||||
void
|
||||
clutter_color_from_hls (ClutterColor *color,
|
||||
float hue,
|
||||
float luminance,
|
||||
float saturation)
|
||||
{
|
||||
float tmp1, tmp2;
|
||||
float tmp3[3];
|
||||
float clr[3];
|
||||
int i;
|
||||
|
||||
hue /= 360.0;
|
||||
|
||||
if (saturation == 0)
|
||||
{
|
||||
color->red = color->green = color->blue = (luminance * 255);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (luminance <= 0.5)
|
||||
tmp2 = luminance * (1.0 + saturation);
|
||||
else
|
||||
tmp2 = luminance + saturation - (luminance * saturation);
|
||||
|
||||
tmp1 = 2.0 * luminance - tmp2;
|
||||
|
||||
tmp3[0] = hue + 1.0 / 3.0;
|
||||
tmp3[1] = hue;
|
||||
tmp3[2] = hue - 1.0 / 3.0;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (tmp3[i] < 0)
|
||||
tmp3[i] += 1.0;
|
||||
|
||||
if (tmp3[i] > 1)
|
||||
tmp3[i] -= 1.0;
|
||||
|
||||
if (6.0 * tmp3[i] < 1.0)
|
||||
clr[i] = tmp1 + (tmp2 - tmp1) * tmp3[i] * 6.0;
|
||||
else if (2.0 * tmp3[i] < 1.0)
|
||||
clr[i] = tmp2;
|
||||
else if (3.0 * tmp3[i] < 2.0)
|
||||
clr[i] = (tmp1 + (tmp2 - tmp1) * ((2.0 / 3.0) - tmp3[i]) * 6.0);
|
||||
else
|
||||
clr[i] = tmp1;
|
||||
}
|
||||
|
||||
color->red = floorf (clr[0] * 255.0 + 0.5);
|
||||
color->green = floorf (clr[1] * 255.0 + 0.5);
|
||||
color->blue = floorf (clr[2] * 255.0 + 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_to_pixel:
|
||||
* @color: a #ClutterColor
|
||||
*
|
||||
* Converts @color into a packed 32 bit integer, containing
|
||||
* all the four 8 bit channels used by #ClutterColor.
|
||||
*
|
||||
* Return value: a packed color
|
||||
*/
|
||||
guint32
|
||||
clutter_color_to_pixel (const ClutterColor *color)
|
||||
{
|
||||
g_return_val_if_fail (color != NULL, 0);
|
||||
|
||||
return (color->alpha |
|
||||
color->blue << 8 |
|
||||
color->green << 16 |
|
||||
color->red << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_from_pixel:
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
* @pixel: a 32 bit packed integer containing a color
|
||||
*
|
||||
* Converts @pixel from the packed representation of a four 8 bit channel
|
||||
* color to a #ClutterColor.
|
||||
*/
|
||||
void
|
||||
clutter_color_from_pixel (ClutterColor *color,
|
||||
guint32 pixel)
|
||||
{
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
color->red = pixel >> 24;
|
||||
color->green = (pixel >> 16) & 0xff;
|
||||
color->blue = (pixel >> 8) & 0xff;
|
||||
color->alpha = pixel & 0xff;
|
||||
}
|
||||
|
||||
static inline void
|
||||
skip_whitespace (gchar **str)
|
||||
{
|
||||
while (g_ascii_isspace (**str))
|
||||
*str += 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
parse_rgb_value (gchar *str,
|
||||
guint8 *color,
|
||||
gchar **endp)
|
||||
{
|
||||
gdouble number;
|
||||
gchar *p;
|
||||
|
||||
skip_whitespace (&str);
|
||||
|
||||
number = g_ascii_strtod (str, endp);
|
||||
|
||||
p = *endp;
|
||||
|
||||
skip_whitespace (&p);
|
||||
|
||||
if (*p == '%')
|
||||
{
|
||||
*endp = (gchar *) (p + 1);
|
||||
|
||||
*color = CLAMP (number / 100.0, 0.0, 1.0) * 255;
|
||||
}
|
||||
else
|
||||
*color = CLAMP (number, 0, 255);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_rgba (ClutterColor *color,
|
||||
gchar *str,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
skip_whitespace (&str);
|
||||
|
||||
if (*str != '(')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* red */
|
||||
parse_rgb_value (str, &color->red, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* green */
|
||||
parse_rgb_value (str, &color->green, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* blue */
|
||||
parse_rgb_value (str, &color->blue, &str);
|
||||
skip_whitespace (&str);
|
||||
|
||||
/* alpha (optional); since the alpha channel value can only
|
||||
* be between 0 and 1 we don't use the parse_rgb_value()
|
||||
* function
|
||||
*/
|
||||
if (has_alpha)
|
||||
{
|
||||
gdouble number;
|
||||
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
|
||||
color->alpha = CLAMP (number * 255.0, 0, 255);
|
||||
}
|
||||
else
|
||||
color->alpha = 255;
|
||||
|
||||
skip_whitespace (&str);
|
||||
if (*str != ')')
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_hsla (ClutterColor *color,
|
||||
gchar *str,
|
||||
gboolean has_alpha)
|
||||
{
|
||||
gdouble number;
|
||||
gdouble h, l, s;
|
||||
|
||||
skip_whitespace (&str);
|
||||
|
||||
if (*str != '(')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* hue */
|
||||
skip_whitespace (&str);
|
||||
/* we don't do any angle normalization here because
|
||||
* clutter_color_from_hls() will do it for us
|
||||
*/
|
||||
number = g_ascii_strtod (str, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
h = number;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* saturation */
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != '%')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
s = CLAMP (number / 100.0, 0.0, 1.0);
|
||||
skip_whitespace (&str);
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
/* luminance */
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
skip_whitespace (&str);
|
||||
if (*str != '%')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
l = CLAMP (number / 100.0, 0.0, 1.0);
|
||||
skip_whitespace (&str);
|
||||
|
||||
/* alpha (optional); since the alpha channel value can only
|
||||
* be between 0 and 1 we don't use the parse_rgb_value()
|
||||
* function
|
||||
*/
|
||||
if (has_alpha)
|
||||
{
|
||||
if (*str != ',')
|
||||
return FALSE;
|
||||
|
||||
str += 1;
|
||||
|
||||
skip_whitespace (&str);
|
||||
number = g_ascii_strtod (str, &str);
|
||||
|
||||
color->alpha = CLAMP (number * 255.0, 0, 255);
|
||||
}
|
||||
else
|
||||
color->alpha = 255;
|
||||
|
||||
skip_whitespace (&str);
|
||||
if (*str != ')')
|
||||
return FALSE;
|
||||
|
||||
clutter_color_from_hls (color, h, l, s);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_from_string:
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
* @str: a string specifying a color
|
||||
*
|
||||
* Parses a string definition of a color, filling the #ClutterColor.red,
|
||||
* #ClutterColor.green, #ClutterColor.blue and #ClutterColor.alpha fields
|
||||
* of @color.
|
||||
*
|
||||
* The @color is not allocated.
|
||||
*
|
||||
* The format of @str can be either one of:
|
||||
*
|
||||
* - a standard name (as taken from the X11 rgb.txt file)
|
||||
* - an hexadecimal value in the form: `#rgb`, `#rrggbb`, `#rgba`, or `#rrggbbaa`
|
||||
* - a RGB color in the form: `rgb(r, g, b)`
|
||||
* - a RGB color in the form: `rgba(r, g, b, a)`
|
||||
* - a HSL color in the form: `hsl(h, s, l)`
|
||||
* -a HSL color in the form: `hsla(h, s, l, a)`
|
||||
*
|
||||
* where 'r', 'g', 'b' and 'a' are (respectively) the red, green, blue color
|
||||
* intensities and the opacity. The 'h', 's' and 'l' are (respectively) the
|
||||
* hue, saturation and luminance values.
|
||||
*
|
||||
* In the rgb() and rgba() formats, the 'r', 'g', and 'b' values are either
|
||||
* integers between 0 and 255, or percentage values in the range between 0%
|
||||
* and 100%; the percentages require the '%' character. The 'a' value, if
|
||||
* specified, can only be a floating point value between 0.0 and 1.0.
|
||||
*
|
||||
* In the hls() and hlsa() formats, the 'h' value (hue) is an angle between
|
||||
* 0 and 360.0 degrees; the 'l' and 's' values (luminance and saturation) are
|
||||
* percentage values in the range between 0% and 100%. The 'a' value, if specified,
|
||||
* can only be a floating point value between 0.0 and 1.0.
|
||||
*
|
||||
* Whitespace inside the definitions is ignored; no leading whitespace
|
||||
* is allowed.
|
||||
*
|
||||
* If the alpha component is not specified then it is assumed to be set to
|
||||
* be fully opaque.
|
||||
*
|
||||
* Return value: %TRUE if parsing succeeded, and %FALSE otherwise
|
||||
*/
|
||||
gboolean
|
||||
clutter_color_from_string (ClutterColor *color,
|
||||
const gchar *str)
|
||||
{
|
||||
PangoColor pango_color = { 0, };
|
||||
|
||||
g_return_val_if_fail (color != NULL, FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
if (strncmp (str, "rgb", 3) == 0)
|
||||
{
|
||||
gchar *s = (gchar *) str;
|
||||
gboolean res;
|
||||
|
||||
if (strncmp (str, "rgba", 4) == 0)
|
||||
res = parse_rgba (color, s + 4, TRUE);
|
||||
else
|
||||
res = parse_rgba (color, s + 3, FALSE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (strncmp (str, "hsl", 3) == 0)
|
||||
{
|
||||
gchar *s = (gchar *) str;
|
||||
gboolean res;
|
||||
|
||||
if (strncmp (str, "hsla", 4) == 0)
|
||||
res = parse_hsla (color, s + 4, TRUE);
|
||||
else
|
||||
res = parse_hsla (color, s + 3, FALSE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* if the string contains a color encoded using the hexadecimal
|
||||
* notations (#rrggbbaa or #rgba) we attempt a rough pass at
|
||||
* parsing the color ourselves, as we need the alpha channel that
|
||||
* Pango can't retrieve.
|
||||
*/
|
||||
if (str[0] == '#' && str[1] != '\0')
|
||||
{
|
||||
gsize length = strlen (str + 1);
|
||||
gint32 result;
|
||||
|
||||
if (sscanf (str + 1, "%x", &result) == 1)
|
||||
{
|
||||
switch (length)
|
||||
{
|
||||
case 8: /* rrggbbaa */
|
||||
color->red = (result >> 24) & 0xff;
|
||||
color->green = (result >> 16) & 0xff;
|
||||
color->blue = (result >> 8) & 0xff;
|
||||
|
||||
color->alpha = result & 0xff;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 6: /* #rrggbb */
|
||||
color->red = (result >> 16) & 0xff;
|
||||
color->green = (result >> 8) & 0xff;
|
||||
color->blue = result & 0xff;
|
||||
|
||||
color->alpha = 0xff;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 4: /* #rgba */
|
||||
color->red = ((result >> 12) & 0xf);
|
||||
color->green = ((result >> 8) & 0xf);
|
||||
color->blue = ((result >> 4) & 0xf);
|
||||
color->alpha = result & 0xf;
|
||||
|
||||
color->red = (color->red << 4) | color->red;
|
||||
color->green = (color->green << 4) | color->green;
|
||||
color->blue = (color->blue << 4) | color->blue;
|
||||
color->alpha = (color->alpha << 4) | color->alpha;
|
||||
|
||||
return TRUE;
|
||||
|
||||
case 3: /* #rgb */
|
||||
color->red = ((result >> 8) & 0xf);
|
||||
color->green = ((result >> 4) & 0xf);
|
||||
color->blue = result & 0xf;
|
||||
|
||||
color->red = (color->red << 4) | color->red;
|
||||
color->green = (color->green << 4) | color->green;
|
||||
color->blue = (color->blue << 4) | color->blue;
|
||||
|
||||
color->alpha = 0xff;
|
||||
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* fall back to pango for X11-style named colors; see:
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/X11_color_names
|
||||
*
|
||||
* for a list. at some point we might even ship with our own list generated
|
||||
* from X11/rgb.txt, like we generate the key symbols.
|
||||
*/
|
||||
if (pango_color_parse (&pango_color, str))
|
||||
{
|
||||
color->red = pango_color.red;
|
||||
color->green = pango_color.green;
|
||||
color->blue = pango_color.blue;
|
||||
|
||||
color->alpha = 0xff;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_to_string:
|
||||
* @color: a #ClutterColor
|
||||
*
|
||||
* Returns a textual specification of @color in the hexadecimal form
|
||||
* `#rrggbbaa`, where `r`, `g`, `b` and `a` are
|
||||
* hexadecimal digits representing the red, green, blue and alpha components
|
||||
* respectively.
|
||||
*
|
||||
* Return value: (transfer full): a newly-allocated text string
|
||||
*/
|
||||
gchar *
|
||||
clutter_color_to_string (const ClutterColor *color)
|
||||
{
|
||||
g_return_val_if_fail (color != NULL, NULL);
|
||||
|
||||
return g_strdup_printf ("#%02x%02x%02x%02x",
|
||||
color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
color->alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_equal:
|
||||
* @v1: (type Clutter.Color): a #ClutterColor
|
||||
* @v2: (type Clutter.Color): a #ClutterColor
|
||||
*
|
||||
* Compares two `ClutterColor`s and checks if they are the same.
|
||||
*
|
||||
* This function can be passed to g_hash_table_new() as the @key_equal_func
|
||||
* parameter, when using `ClutterColor`s as keys in a #GHashTable.
|
||||
*
|
||||
* Return value: %TRUE if the two colors are the same.
|
||||
*/
|
||||
gboolean
|
||||
clutter_color_equal (gconstpointer v1,
|
||||
gconstpointer v2)
|
||||
{
|
||||
const ClutterColor *a, *b;
|
||||
|
||||
g_return_val_if_fail (v1 != NULL, FALSE);
|
||||
g_return_val_if_fail (v2 != NULL, FALSE);
|
||||
|
||||
if (v1 == v2)
|
||||
return TRUE;
|
||||
|
||||
a = v1;
|
||||
b = v2;
|
||||
|
||||
return (a->red == b->red &&
|
||||
a->green == b->green &&
|
||||
a->blue == b->blue &&
|
||||
a->alpha == b->alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_hash:
|
||||
* @v: (type Clutter.Color): a #ClutterColor
|
||||
*
|
||||
* Converts a #ClutterColor to a hash value.
|
||||
*
|
||||
* This function can be passed to g_hash_table_new() as the @hash_func
|
||||
* parameter, when using `ClutterColor`s as keys in a #GHashTable.
|
||||
*
|
||||
* Return value: a hash value corresponding to the color
|
||||
*/
|
||||
guint
|
||||
clutter_color_hash (gconstpointer v)
|
||||
{
|
||||
return clutter_color_to_pixel ((const ClutterColor *) v);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_interpolate:
|
||||
* @initial: the initial #ClutterColor
|
||||
* @final: the final #ClutterColor
|
||||
* @progress: the interpolation progress
|
||||
* @result: (out): return location for the interpolation
|
||||
*
|
||||
* Interpolates between @initial and @final `ClutterColor`s
|
||||
* using @progress
|
||||
*/
|
||||
void
|
||||
clutter_color_interpolate (const ClutterColor *initial,
|
||||
const ClutterColor *final,
|
||||
gdouble progress,
|
||||
ClutterColor *result)
|
||||
{
|
||||
g_return_if_fail (initial != NULL);
|
||||
g_return_if_fail (final != NULL);
|
||||
g_return_if_fail (result != NULL);
|
||||
|
||||
result->red = initial->red + (final->red - initial->red) * progress;
|
||||
result->green = initial->green + (final->green - initial->green) * progress;
|
||||
result->blue = initial->blue + (final->blue - initial->blue) * progress;
|
||||
result->alpha = initial->alpha + (final->alpha - initial->alpha) * progress;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_color_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
gdouble progress,
|
||||
GValue *retval)
|
||||
{
|
||||
const ClutterColor *a_color = clutter_value_get_color (a);
|
||||
const ClutterColor *b_color = clutter_value_get_color (b);
|
||||
ClutterColor res = { 0, };
|
||||
|
||||
clutter_color_interpolate (a_color, b_color, progress, &res);
|
||||
clutter_value_set_color (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_copy:
|
||||
* @color: a #ClutterColor
|
||||
*
|
||||
* Makes a copy of the color structure. The result must be
|
||||
* freed using [method@Clutter.Color.free].
|
||||
*
|
||||
* Return value: (transfer full): an allocated copy of @color.
|
||||
*/
|
||||
ClutterColor *
|
||||
clutter_color_copy (const ClutterColor *color)
|
||||
{
|
||||
if (G_LIKELY (color != NULL))
|
||||
return g_memdup2 (color, sizeof (ClutterColor));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_free:
|
||||
* @color: a #ClutterColor
|
||||
*
|
||||
* Frees a color structure created with [method@Clutter.Color.copy].
|
||||
*/
|
||||
void
|
||||
clutter_color_free (ClutterColor *color)
|
||||
{
|
||||
if (G_LIKELY (color != NULL))
|
||||
g_free (color);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_new:
|
||||
* @red: red component of the color, between 0 and 255
|
||||
* @green: green component of the color, between 0 and 255
|
||||
* @blue: blue component of the color, between 0 and 255
|
||||
* @alpha: alpha component of the color, between 0 and 255
|
||||
*
|
||||
* Creates a new #ClutterColor with the given values.
|
||||
*
|
||||
* This function is the equivalent of:
|
||||
*
|
||||
* ```c
|
||||
* clutter_color_init (clutter_color_alloc (), red, green, blue, alpha);
|
||||
* ```
|
||||
*
|
||||
* Return value: (transfer full): the newly allocated color.
|
||||
* Use [method@Clutter.Color.free] when done
|
||||
*/
|
||||
ClutterColor *
|
||||
clutter_color_new (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha)
|
||||
{
|
||||
return clutter_color_init (clutter_color_alloc (),
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_alloc: (constructor)
|
||||
*
|
||||
* Allocates a new, transparent black #ClutterColor.
|
||||
*
|
||||
* Return value: (transfer full): the newly allocated #ClutterColor; use
|
||||
* [method@Clutter.Color.free] to free its resources
|
||||
*/
|
||||
ClutterColor *
|
||||
clutter_color_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterColor, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_color_init:
|
||||
* @color: a #ClutterColor
|
||||
* @red: red component of the color, between 0 and 255
|
||||
* @green: green component of the color, between 0 and 255
|
||||
* @blue: blue component of the color, between 0 and 255
|
||||
* @alpha: alpha component of the color, between 0 and 255
|
||||
*
|
||||
* Initializes @color with the given values.
|
||||
*
|
||||
* Return value: (transfer none): the initialized #ClutterColor
|
||||
*/
|
||||
ClutterColor *
|
||||
clutter_color_init (ClutterColor *color,
|
||||
guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha)
|
||||
{
|
||||
g_return_val_if_fail (color != NULL, NULL);
|
||||
|
||||
color->red = red;
|
||||
color->green = green;
|
||||
color->blue = blue;
|
||||
color->alpha = alpha;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_value_transform_color_string (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
const ClutterColor *color = g_value_get_boxed (src);
|
||||
|
||||
if (color)
|
||||
{
|
||||
gchar *string = clutter_color_to_string (color);
|
||||
|
||||
g_value_take_string (dest, string);
|
||||
}
|
||||
else
|
||||
g_value_set_string (dest, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_value_transform_string_color (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
const char *str = g_value_get_string (src);
|
||||
|
||||
if (str)
|
||||
{
|
||||
ClutterColor color = { 0, };
|
||||
|
||||
clutter_color_from_string (&color, str);
|
||||
|
||||
clutter_value_set_color (dest, &color);
|
||||
}
|
||||
else
|
||||
clutter_value_set_color (dest, NULL);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterColor, clutter_color,
|
||||
clutter_color_copy,
|
||||
clutter_color_free,
|
||||
CLUTTER_REGISTER_VALUE_TRANSFORM_TO (G_TYPE_STRING, clutter_value_transform_color_string)
|
||||
CLUTTER_REGISTER_VALUE_TRANSFORM_FROM (G_TYPE_STRING, clutter_value_transform_string_color)
|
||||
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_color_progress));
|
||||
|
||||
/**
|
||||
* clutter_value_set_color:
|
||||
* @value: a #GValue initialized to #CLUTTER_TYPE_COLOR
|
||||
* @color: the color to set
|
||||
*
|
||||
* Sets @value to @color.
|
||||
*/
|
||||
void
|
||||
clutter_value_set_color (GValue *value,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_VALUE_HOLDS_COLOR (value));
|
||||
|
||||
g_value_set_boxed (value, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_value_get_color:
|
||||
* @value: a #GValue initialized to #CLUTTER_TYPE_COLOR
|
||||
*
|
||||
* Gets the #ClutterColor contained in @value.
|
||||
*
|
||||
* Return value: (transfer none): the color inside the passed #GValue
|
||||
*/
|
||||
const ClutterColor *
|
||||
clutter_value_get_color (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_COLOR (value), NULL);
|
||||
|
||||
return g_value_get_boxed (value);
|
||||
}
|
||||
|
||||
static void
|
||||
param_color_init (GParamSpec *pspec)
|
||||
{
|
||||
ClutterParamSpecColor *cspec = CLUTTER_PARAM_SPEC_COLOR (pspec);
|
||||
|
||||
cspec->default_value = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
param_color_finalize (GParamSpec *pspec)
|
||||
{
|
||||
ClutterParamSpecColor *cspec = CLUTTER_PARAM_SPEC_COLOR (pspec);
|
||||
|
||||
clutter_color_free (cspec->default_value);
|
||||
}
|
||||
|
||||
static void
|
||||
param_color_set_default (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
const ClutterColor *default_value =
|
||||
CLUTTER_PARAM_SPEC_COLOR (pspec)->default_value;
|
||||
clutter_value_set_color (value, default_value);
|
||||
}
|
||||
|
||||
static gint
|
||||
param_color_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2)
|
||||
{
|
||||
const ClutterColor *color1 = g_value_get_boxed (value1);
|
||||
const ClutterColor *color2 = g_value_get_boxed (value2);
|
||||
int pixel1, pixel2;
|
||||
|
||||
if (color1 == NULL)
|
||||
return color2 == NULL ? 0 : -1;
|
||||
|
||||
pixel1 = clutter_color_to_pixel (color1);
|
||||
pixel2 = clutter_color_to_pixel (color2);
|
||||
|
||||
if (pixel1 < pixel2)
|
||||
return -1;
|
||||
else if (pixel1 == pixel2)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
GType
|
||||
clutter_param_color_get_type (void)
|
||||
{
|
||||
static GType pspec_type = 0;
|
||||
|
||||
if (G_UNLIKELY (pspec_type == 0))
|
||||
{
|
||||
const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (ClutterParamSpecColor),
|
||||
16,
|
||||
param_color_init,
|
||||
CLUTTER_TYPE_COLOR,
|
||||
param_color_finalize,
|
||||
param_color_set_default,
|
||||
NULL,
|
||||
param_color_values_cmp,
|
||||
};
|
||||
|
||||
pspec_type = g_param_type_register_static (I_("ClutterParamSpecColor"),
|
||||
&pspec_info);
|
||||
}
|
||||
|
||||
return pspec_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_param_spec_color: (skip)
|
||||
* @name: name of the property
|
||||
* @nick: short name
|
||||
* @blurb: description (can be translatable)
|
||||
* @default_value: default value
|
||||
* @flags: flags for the param spec
|
||||
*
|
||||
* Creates a #GParamSpec for properties using #ClutterColor.
|
||||
*
|
||||
* Return value: the newly created #GParamSpec
|
||||
*/
|
||||
GParamSpec *
|
||||
clutter_param_spec_color (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
const ClutterColor *default_value,
|
||||
GParamFlags flags)
|
||||
{
|
||||
ClutterParamSpecColor *cspec;
|
||||
|
||||
cspec = g_param_spec_internal (CLUTTER_TYPE_PARAM_COLOR,
|
||||
name, nick, blurb, flags);
|
||||
|
||||
cspec->default_value = clutter_color_copy (default_value);
|
||||
|
||||
return G_PARAM_SPEC (cspec);
|
||||
}
|
182
mutter/clutter/clutter/clutter-color.h
Normal file
182
mutter/clutter/clutter/clutter-color.h
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Matthew Allum <mallum@openedhand.com>
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2006, 2007, 2008 OpenedHand
|
||||
* Copyright (C) 2009 Intel Corp.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_COLOR (clutter_color_get_type ())
|
||||
|
||||
/**
|
||||
* ClutterColor:
|
||||
* @red: red component, between 0 and 255
|
||||
* @green: green component, between 0 and 255
|
||||
* @blue: blue component, between 0 and 255
|
||||
* @alpha: alpha component, between 0 and 255
|
||||
*
|
||||
* A simple type for representing colors.
|
||||
*
|
||||
* A #ClutterColor is expressed as a 4-tuple of values ranging from
|
||||
* zero to 255, one for each color channel plus one for the alpha.
|
||||
*
|
||||
* The alpha channel is fully opaque at 255 and fully transparent at 0.
|
||||
*/
|
||||
struct _ClutterColor
|
||||
{
|
||||
/*< public >*/
|
||||
guint8 red;
|
||||
guint8 green;
|
||||
guint8 blue;
|
||||
|
||||
guint8 alpha;
|
||||
};
|
||||
|
||||
/**
|
||||
* CLUTTER_COLOR_INIT:
|
||||
* @r: value for the red channel, between 0 and 255
|
||||
* @g: value for the green channel, between 0 and 255
|
||||
* @b: value for the blue channel, between 0 and 255
|
||||
* @a: value for the alpha channel, between 0 and 255
|
||||
*
|
||||
* A macro that initializes a #ClutterColor, to be used when declaring it.
|
||||
*/
|
||||
#define CLUTTER_COLOR_INIT(_r, _g, _b, _a) \
|
||||
(ClutterColor) { \
|
||||
.red = (_r), \
|
||||
.green = (_g), \
|
||||
.blue = (_b), \
|
||||
.alpha = (_a) \
|
||||
}
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_color_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterColor *clutter_color_new (guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha);
|
||||
CLUTTER_EXPORT
|
||||
ClutterColor *clutter_color_alloc (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterColor *clutter_color_init (ClutterColor *color,
|
||||
guint8 red,
|
||||
guint8 green,
|
||||
guint8 blue,
|
||||
guint8 alpha);
|
||||
CLUTTER_EXPORT
|
||||
ClutterColor *clutter_color_copy (const ClutterColor *color);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_free (ClutterColor *color);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gchar * clutter_color_to_string (const ClutterColor *color);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_color_from_string (ClutterColor *color,
|
||||
const gchar *str);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_to_hls (const ClutterColor *color,
|
||||
gfloat *hue,
|
||||
gfloat *luminance,
|
||||
gfloat *saturation);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_from_hls (ClutterColor *color,
|
||||
gfloat hue,
|
||||
gfloat luminance,
|
||||
gfloat saturation);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint32 clutter_color_to_pixel (const ClutterColor *color);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_from_pixel (ClutterColor *color,
|
||||
guint32 pixel);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_color_hash (gconstpointer v);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_color_equal (gconstpointer v1,
|
||||
gconstpointer v2);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_color_interpolate (const ClutterColor *initial,
|
||||
const ClutterColor *final,
|
||||
gdouble progress,
|
||||
ClutterColor *result);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColor, clutter_color_free)
|
||||
|
||||
#define CLUTTER_TYPE_PARAM_COLOR (clutter_param_color_get_type ())
|
||||
#define CLUTTER_PARAM_SPEC_COLOR(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), CLUTTER_TYPE_PARAM_COLOR, ClutterParamSpecColor))
|
||||
#define CLUTTER_IS_PARAM_SPEC_COLOR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), CLUTTER_TYPE_PARAM_COLOR))
|
||||
|
||||
/**
|
||||
* CLUTTER_VALUE_HOLDS_COLOR:
|
||||
* @x: a #GValue
|
||||
*
|
||||
* Evaluates to %TRUE if @x holds a `ClutterColor`.
|
||||
*/
|
||||
#define CLUTTER_VALUE_HOLDS_COLOR(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_COLOR))
|
||||
|
||||
typedef struct _ClutterParamSpecColor ClutterParamSpecColor;
|
||||
|
||||
/**
|
||||
* ClutterParamSpecColor: (skip)
|
||||
* @default_value: default color value
|
||||
*
|
||||
* A #GParamSpec subclass for defining properties holding
|
||||
* a #ClutterColor.
|
||||
*/
|
||||
struct _ClutterParamSpecColor
|
||||
{
|
||||
/*< private >*/
|
||||
GParamSpec parent_instance;
|
||||
|
||||
/*< public >*/
|
||||
ClutterColor *default_value;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_value_set_color (GValue *value,
|
||||
const ClutterColor *color);
|
||||
CLUTTER_EXPORT
|
||||
const ClutterColor * clutter_value_get_color (const GValue *value);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_param_color_get_type (void) G_GNUC_CONST;
|
||||
CLUTTER_EXPORT
|
||||
GParamSpec * clutter_param_spec_color (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
const ClutterColor *default_value,
|
||||
GParamFlags flags);
|
||||
|
||||
G_END_DECLS
|
297
mutter/clutter/clutter/clutter-colorize-effect.c
Normal file
297
mutter/clutter/clutter/clutter-colorize-effect.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterColorizeEffect:
|
||||
*
|
||||
* A colorization effect
|
||||
*
|
||||
* #ClutterColorizeEffect is a sub-class of #ClutterEffect that
|
||||
* colorizes an actor with the given tint.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-colorize-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
typedef struct _ClutterColorizeEffectPrivate
|
||||
{
|
||||
ClutterOffscreenEffect parent_instance;
|
||||
|
||||
/* the tint of the colorization */
|
||||
ClutterColor tint;
|
||||
|
||||
gint tint_uniform;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
} ClutterColorizeEffectPrivate;
|
||||
|
||||
/* the magic gray vec3 has been taken from the NTSC conversion weights
|
||||
* as defined by:
|
||||
*
|
||||
* "OpenGL Superbible, 4th Edition"
|
||||
* -- Richard S. Wright Jr, Benjamin Lipchak, Nicholas Haemel
|
||||
* Addison-Wesley
|
||||
*/
|
||||
static const gchar *colorize_glsl_declarations =
|
||||
"uniform vec3 tint;\n";
|
||||
|
||||
static const gchar *colorize_glsl_source =
|
||||
"float gray = dot (cogl_color_out.rgb, vec3 (0.299, 0.587, 0.114));\n"
|
||||
"cogl_color_out.rgb = gray * tint;\n";
|
||||
|
||||
/* a lame sepia */
|
||||
static const ClutterColor default_tint = { 255, 204, 153, 255 };
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_TINT,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (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);
|
||||
ClutterColorizeEffectPrivate *priv =
|
||||
clutter_colorize_effect_get_instance_private (colorize_effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
|
||||
return g_object_ref (priv->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (gobject);
|
||||
ClutterColorizeEffectPrivate *priv =
|
||||
clutter_colorize_effect_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->pipeline);
|
||||
|
||||
G_OBJECT_CLASS (clutter_colorize_effect_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterColorizeEffect *effect = CLUTTER_COLORIZE_EFFECT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TINT:
|
||||
clutter_colorize_effect_set_tint (effect,
|
||||
clutter_value_get_color (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterColorizeEffect *effect = CLUTTER_COLORIZE_EFFECT (gobject);
|
||||
ClutterColorizeEffectPrivate *priv =
|
||||
clutter_colorize_effect_get_instance_private (effect);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_TINT:
|
||||
clutter_value_set_color (value, &priv->tint);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_colorize_effect_create_pipeline;
|
||||
|
||||
gobject_class->set_property = clutter_colorize_effect_set_property;
|
||||
gobject_class->get_property = clutter_colorize_effect_get_property;
|
||||
gobject_class->dispose = clutter_colorize_effect_dispose;
|
||||
|
||||
/**
|
||||
* ClutterColorizeEffect:tint:
|
||||
*
|
||||
* The tint to apply to the actor
|
||||
*/
|
||||
obj_props[PROP_TINT] =
|
||||
clutter_param_spec_color ("tint", NULL, NULL,
|
||||
&default_tint,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
update_tint_uniform (ClutterColorizeEffect *self)
|
||||
{
|
||||
ClutterColorizeEffectPrivate *priv =
|
||||
clutter_colorize_effect_get_instance_private (self);
|
||||
if (priv->tint_uniform > -1)
|
||||
{
|
||||
float tint[3] = {
|
||||
priv->tint.red / 255.0,
|
||||
priv->tint.green / 255.0,
|
||||
priv->tint.blue / 255.0
|
||||
};
|
||||
|
||||
cogl_pipeline_set_uniform_float (priv->pipeline,
|
||||
priv->tint_uniform,
|
||||
3, /* n_components */
|
||||
1, /* count */
|
||||
tint);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_colorize_effect_init (ClutterColorizeEffect *self)
|
||||
{
|
||||
ClutterColorizeEffectClass *klass = CLUTTER_COLORIZE_EFFECT_GET_CLASS (self);
|
||||
ClutterColorizeEffectPrivate *priv =
|
||||
clutter_colorize_effect_get_instance_private (self);
|
||||
if (G_UNLIKELY (klass->base_pipeline == NULL))
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
klass->base_pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
|
||||
colorize_glsl_declarations,
|
||||
colorize_glsl_source);
|
||||
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
|
||||
g_object_unref (snippet);
|
||||
|
||||
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
|
||||
}
|
||||
|
||||
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
||||
|
||||
priv->tint_uniform =
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline, "tint");
|
||||
|
||||
priv->tint = default_tint;
|
||||
|
||||
update_tint_uniform (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_colorize_effect_new:
|
||||
* @tint: the color to be used
|
||||
*
|
||||
* Creates a new #ClutterColorizeEffect to be used with
|
||||
* [method@Clutter.Actor.add_effect]
|
||||
*
|
||||
* Return value: the newly created #ClutterColorizeEffect or %NULL
|
||||
*/
|
||||
ClutterEffect *
|
||||
clutter_colorize_effect_new (const ClutterColor *tint)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_COLORIZE_EFFECT,
|
||||
"tint", tint,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_colorize_effect_set_tint:
|
||||
* @effect: a #ClutterColorizeEffect
|
||||
* @tint: the color to be used
|
||||
*
|
||||
* Sets the tint to be used when colorizing
|
||||
*/
|
||||
void
|
||||
clutter_colorize_effect_set_tint (ClutterColorizeEffect *effect,
|
||||
const ClutterColor *tint)
|
||||
{
|
||||
ClutterColorizeEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_COLORIZE_EFFECT (effect));
|
||||
|
||||
priv = clutter_colorize_effect_get_instance_private (effect);
|
||||
priv->tint = *tint;
|
||||
|
||||
update_tint_uniform (effect);
|
||||
|
||||
clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_TINT]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_colorize_effect_get_tint:
|
||||
* @effect: a #ClutterColorizeEffect
|
||||
* @tint: (out caller-allocates): return location for the color used
|
||||
*
|
||||
* Retrieves the tint used by @effect
|
||||
*/
|
||||
void
|
||||
clutter_colorize_effect_get_tint (ClutterColorizeEffect *effect,
|
||||
ClutterColor *tint)
|
||||
{
|
||||
ClutterColorizeEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_COLORIZE_EFFECT (effect));
|
||||
g_return_if_fail (tint != NULL);
|
||||
|
||||
priv = clutter_colorize_effect_get_instance_private (effect);
|
||||
*tint = priv->tint;
|
||||
}
|
62
mutter/clutter/clutter/clutter-colorize-effect.h
Normal file
62
mutter/clutter/clutter/clutter-colorize-effect.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-color.h"
|
||||
#include "clutter/clutter-effect.h"
|
||||
#include "clutter/clutter-offscreen-effect.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_COLORIZE_EFFECT (clutter_colorize_effect_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterColorizeEffect,
|
||||
clutter_colorize_effect,
|
||||
CLUTTER, COLORIZE_EFFECT,
|
||||
ClutterOffscreenEffect)
|
||||
|
||||
struct _ClutterColorizeEffectClass
|
||||
{
|
||||
ClutterOffscreenEffectClass parent_class;
|
||||
|
||||
CoglPipeline *base_pipeline;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterEffect *clutter_colorize_effect_new (const ClutterColor *tint);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_colorize_effect_set_tint (ClutterColorizeEffect *effect,
|
||||
const ClutterColor *tint);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_colorize_effect_get_tint (ClutterColorizeEffect *effect,
|
||||
ClutterColor *tint);
|
||||
|
||||
G_END_DECLS
|
32
mutter/clutter/clutter/clutter-constraint-private.h
Normal file
32
mutter/clutter/clutter/clutter-constraint-private.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-constraint.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean clutter_constraint_update_allocation (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterActorBox *allocation);
|
||||
|
||||
G_END_DECLS
|
218
mutter/clutter/clutter/clutter-constraint.c
Normal file
218
mutter/clutter/clutter/clutter-constraint.c
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterConstraint:
|
||||
*
|
||||
* Abstract class for constraints on position or size
|
||||
*
|
||||
* #ClutterConstraint is a base abstract class for modifiers of a #ClutterActor
|
||||
* position or size.
|
||||
*
|
||||
* A #ClutterConstraint sub-class should contain the logic for modifying
|
||||
* the position or size of the #ClutterActor to which it is applied, by
|
||||
* updating the actor's allocation. Each #ClutterConstraint can change the
|
||||
* allocation of the actor to which they are applied by overriding the
|
||||
* [vfunc@Clutter.Constraint.update_allocation] virtual function.
|
||||
*
|
||||
* ## Using Constraints
|
||||
*
|
||||
* Constraints can be used with fixed layout managers, like
|
||||
* #ClutterFixedLayout, or with actors implicitly using a fixed layout
|
||||
* manager, like #ClutterGroup and #ClutterStage.
|
||||
*
|
||||
* Constraints provide a way to build user interfaces by using
|
||||
* relations between #ClutterActors, without explicit fixed
|
||||
* positioning and sizing, similarly to how fluid layout managers like
|
||||
* #ClutterBoxLayout lay out their children.
|
||||
*
|
||||
* Constraints are attached to a #ClutterActor, and are available
|
||||
* for inspection using [method@Clutter.Actor.get_constraints].
|
||||
*
|
||||
* Clutter provides different implementation of the #ClutterConstraint
|
||||
* abstract class, for instance:
|
||||
*
|
||||
* - #ClutterAlignConstraint, a constraint that can be used to align
|
||||
* an actor to another one on either the horizontal or the vertical
|
||||
* axis, using a normalized value between 0 and 1.
|
||||
* - #ClutterBindConstraint, a constraint binds the X, Y, width or height
|
||||
* of an actor to the corresponding position or size of a source actor,
|
||||
* with or without an offset.
|
||||
* - #ClutterSnapConstraint, a constraint that "snaps" together the edges
|
||||
* of two #ClutterActors; if an actor uses two constraints on both its
|
||||
* horizontal or vertical edges then it can also expand to fit the empty
|
||||
* space.
|
||||
*
|
||||
* It is important to note that Clutter does not avoid loops or
|
||||
* competing constraints; if two or more #ClutterConstraints
|
||||
* are operating on the same positional or dimensional attributes of an
|
||||
* actor, or if the constraints on two different actors depend on each
|
||||
* other, then the behavior is undefined.
|
||||
*
|
||||
* ## Implementing a ClutterConstraint
|
||||
*
|
||||
* Creating a sub-class of #ClutterConstraint requires the
|
||||
* implementation of the [vfunc@Clutter.Constraint.update_allocation]
|
||||
* virtual function.
|
||||
*
|
||||
* The `update_allocation()` virtual function is called during the
|
||||
* allocation sequence of a #ClutterActor, and allows any #ClutterConstraint
|
||||
* attached to that actor to modify the allocation before it is passed to
|
||||
* the actor's #ClutterActorClass.allocate() implementation.
|
||||
*
|
||||
* The #ClutterActorBox passed to the `update_allocation()` implementation
|
||||
* contains the original allocation of the #ClutterActor, plus the eventual
|
||||
* modifications applied by the other #ClutterConstraints, in the same order
|
||||
* the constraints have been applied to the actor.
|
||||
*
|
||||
* It is not necessary for a #ClutterConstraint sub-class to chain
|
||||
* up to the parent's implementation.
|
||||
*
|
||||
* If a #ClutterConstraint is parametrized - i.e. if it contains
|
||||
* properties that affect the way the constraint is implemented - it should
|
||||
* call clutter_actor_queue_relayout() on the actor to which it is attached
|
||||
* to whenever any parameter is changed. The actor to which it is attached
|
||||
* can be recovered at any point using clutter_actor_meta_get_actor().
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "clutter/clutter-constraint-private.h"
|
||||
|
||||
#include "clutter/clutter-actor.h"
|
||||
#include "clutter/clutter-actor-meta-private.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterConstraint,
|
||||
clutter_constraint,
|
||||
CLUTTER_TYPE_ACTOR_META);
|
||||
|
||||
static void
|
||||
constraint_update_allocation (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterActorBox *allocation)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
constraint_update_preferred_size (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterOrientation direction,
|
||||
float for_size,
|
||||
float *minimum_size,
|
||||
float *natural_size)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_constraint_set_enabled (ClutterActorMeta *meta,
|
||||
gboolean is_enabled)
|
||||
{
|
||||
ClutterActorMetaClass *parent_class =
|
||||
CLUTTER_ACTOR_META_CLASS (clutter_constraint_parent_class);
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (meta);
|
||||
if (actor)
|
||||
clutter_actor_queue_relayout (actor);
|
||||
|
||||
parent_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_constraint_class_init (ClutterConstraintClass *klass)
|
||||
{
|
||||
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
|
||||
actor_meta_class->set_enabled = clutter_constraint_set_enabled;
|
||||
|
||||
klass->update_allocation = constraint_update_allocation;
|
||||
klass->update_preferred_size = constraint_update_preferred_size;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_constraint_init (ClutterConstraint *self)
|
||||
{
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_constraint_update_allocation:
|
||||
* @constraint: a #ClutterConstraint
|
||||
* @actor: a #ClutterActor
|
||||
* @allocation: (inout): the allocation to modify
|
||||
*
|
||||
* Asks the @constraint to update the @allocation of a #ClutterActor.
|
||||
*
|
||||
* Returns: %TRUE if the allocation was updated
|
||||
*/
|
||||
gboolean
|
||||
clutter_constraint_update_allocation (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterActorBox *allocation)
|
||||
{
|
||||
ClutterActorBox old_alloc;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_CONSTRAINT (constraint), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), FALSE);
|
||||
g_return_val_if_fail (allocation != NULL, FALSE);
|
||||
|
||||
old_alloc = *allocation;
|
||||
|
||||
CLUTTER_CONSTRAINT_GET_CLASS (constraint)->update_allocation (constraint,
|
||||
actor,
|
||||
allocation);
|
||||
|
||||
return !clutter_actor_box_equal (allocation, &old_alloc);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_constraint_update_preferred_size:
|
||||
* @constraint: a #ClutterConstraint
|
||||
* @actor: a #ClutterActor
|
||||
* @direction: a #ClutterOrientation
|
||||
* @for_size: the size in the opposite direction
|
||||
* @minimum_size: (inout): the minimum size to modify
|
||||
* @natural_size: (inout): the natural size to modify
|
||||
*
|
||||
* Asks the @constraint to update the size request of a #ClutterActor.
|
||||
*/
|
||||
void
|
||||
clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterOrientation direction,
|
||||
float for_size,
|
||||
float *minimum_size,
|
||||
float *natural_size)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
CLUTTER_CONSTRAINT_GET_CLASS (constraint)->update_preferred_size (constraint, actor,
|
||||
direction,
|
||||
for_size,
|
||||
minimum_size,
|
||||
natural_size);
|
||||
}
|
106
mutter/clutter/clutter/clutter-constraint.h
Normal file
106
mutter/clutter/clutter/clutter-constraint.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-actor-meta.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_CONSTRAINT (clutter_constraint_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterConstraint,
|
||||
clutter_constraint,
|
||||
CLUTTER,
|
||||
CONSTRAINT,
|
||||
ClutterActorMeta)
|
||||
|
||||
/**
|
||||
* ClutterConstraintClass:
|
||||
* @update_allocation: virtual function used to update the allocation
|
||||
* of the #ClutterActor using the #ClutterConstraint
|
||||
* @update_preferred_size: virtual function used to update the preferred
|
||||
* size of the #ClutterActor using the #ClutterConstraint; optional,
|
||||
* since 1.22
|
||||
*
|
||||
* The #ClutterConstraintClass structure contains
|
||||
* only private data
|
||||
*/
|
||||
struct _ClutterConstraintClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorMetaClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (* update_allocation) (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterActorBox *allocation);
|
||||
|
||||
void (* update_preferred_size) (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterOrientation direction,
|
||||
float for_size,
|
||||
float *minimum_size,
|
||||
float *natural_size);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
|
||||
ClutterActor *actor,
|
||||
ClutterOrientation direction,
|
||||
float for_size,
|
||||
float *minimum_size,
|
||||
float *natural_size);
|
||||
|
||||
/* ClutterActor API */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_constraint (ClutterActor *self,
|
||||
ClutterConstraint *constraint);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_constraint_with_name (ClutterActor *self,
|
||||
const gchar *name,
|
||||
ClutterConstraint *constraint);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_constraint (ClutterActor *self,
|
||||
ClutterConstraint *constraint);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_constraint_by_name (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_actor_get_constraints (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterConstraint *clutter_actor_get_constraint (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_clear_constraints (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_constraints (ClutterActor *self);
|
||||
|
||||
G_END_DECLS
|
41
mutter/clutter/clutter/clutter-content-private.h
Normal file
41
mutter/clutter/clutter/clutter-content-private.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-content.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void _clutter_content_attached (ClutterContent *content,
|
||||
ClutterActor *actor);
|
||||
void _clutter_content_detached (ClutterContent *content,
|
||||
ClutterActor *actor);
|
||||
|
||||
void _clutter_content_paint_content (ClutterContent *content,
|
||||
ClutterActor *actor,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
G_END_DECLS
|
339
mutter/clutter/clutter/clutter-content.c
Normal file
339
mutter/clutter/clutter/clutter-content.c
Normal file
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterContent:
|
||||
*
|
||||
* Delegate for painting the content of an actor
|
||||
*
|
||||
* #ClutterContent is an interface to implement types responsible for
|
||||
* painting the content of a [class@Actor].
|
||||
*
|
||||
* Multiple actors can use the same #ClutterContent instance, in order
|
||||
* to share the resources associated with painting the same content..
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#include "clutter/clutter-content-private.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-marshal.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
ATTACHED,
|
||||
DETACHED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static GQuark quark_content_actors = 0;
|
||||
|
||||
static guint content_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
G_DEFINE_INTERFACE (ClutterContent, clutter_content, G_TYPE_OBJECT)
|
||||
|
||||
static gboolean
|
||||
clutter_content_real_get_preferred_size (ClutterContent *content,
|
||||
gfloat *width,
|
||||
gfloat *height)
|
||||
{
|
||||
if (width != NULL)
|
||||
*width = 0.f;
|
||||
|
||||
if (height != NULL)
|
||||
*height = 0.f;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_real_attached (ClutterContent *content,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_real_detached (ClutterContent *content,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_real_invalidate (ClutterContent *content)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_real_invalidate_size (ClutterContent *content)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_real_paint_content (ClutterContent *content,
|
||||
ClutterActor *actor,
|
||||
ClutterPaintNode *context,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_content_default_init (ClutterContentInterface *iface)
|
||||
{
|
||||
quark_content_actors = g_quark_from_static_string ("-clutter-content-actors");
|
||||
|
||||
iface->get_preferred_size = clutter_content_real_get_preferred_size;
|
||||
iface->paint_content = clutter_content_real_paint_content;
|
||||
iface->attached = clutter_content_real_attached;
|
||||
iface->detached = clutter_content_real_detached;
|
||||
iface->invalidate = clutter_content_real_invalidate;
|
||||
iface->invalidate_size = clutter_content_real_invalidate_size;
|
||||
|
||||
/**
|
||||
* ClutterContent::attached:
|
||||
* @content: the object that emitted the signal
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* This signal is emitted each time a #ClutterContent implementation is
|
||||
* assigned to a #ClutterActor.
|
||||
*/
|
||||
content_signals[ATTACHED] =
|
||||
g_signal_new (I_("attached"),
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (ClutterContentInterface, attached),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
|
||||
/**
|
||||
* ClutterContent::detached:
|
||||
* @content: the object that emitted the signal
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* This signal is emitted each time a #ClutterContent implementation is
|
||||
* removed from a #ClutterActor.
|
||||
*/
|
||||
content_signals[DETACHED] =
|
||||
g_signal_new (I_("detached"),
|
||||
G_TYPE_FROM_INTERFACE (iface),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (ClutterContentInterface, detached),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_ACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_content_invalidate:
|
||||
* @content: a #ClutterContent
|
||||
*
|
||||
* Invalidates a #ClutterContent.
|
||||
*
|
||||
* This function should be called by #ClutterContent implementations when
|
||||
* they change the way a the content should be painted regardless of the
|
||||
* actor state.
|
||||
*/
|
||||
void
|
||||
clutter_content_invalidate (ClutterContent *content)
|
||||
{
|
||||
GHashTable *actors;
|
||||
GHashTableIter iter;
|
||||
gpointer key_p, value_p;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CONTENT (content));
|
||||
|
||||
CLUTTER_CONTENT_GET_IFACE (content)->invalidate (content);
|
||||
|
||||
actors = g_object_get_qdata (G_OBJECT (content), quark_content_actors);
|
||||
if (actors == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_iter_init (&iter, actors);
|
||||
while (g_hash_table_iter_next (&iter, &key_p, &value_p))
|
||||
{
|
||||
ClutterActor *actor = key_p;
|
||||
|
||||
g_assert (actor != NULL);
|
||||
|
||||
clutter_actor_queue_redraw (actor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_content_invalidate_size:
|
||||
* @content: a #ClutterContent
|
||||
*
|
||||
* Signals that @content's size changed. Attached actors with request mode
|
||||
* set to %CLUTTER_REQUEST_CONTENT_SIZE will have a relayout queued.
|
||||
*
|
||||
* Attached actors with other request modes are not redrawn. To redraw them
|
||||
* too, use [method@Clutter.Content.invalidate].
|
||||
*/
|
||||
void
|
||||
clutter_content_invalidate_size (ClutterContent *content)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
GHashTable *actors;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CONTENT (content));
|
||||
|
||||
CLUTTER_CONTENT_GET_IFACE (content)->invalidate_size (content);
|
||||
|
||||
actors = g_object_get_qdata (G_OBJECT (content), quark_content_actors);
|
||||
if (actors == NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_iter_init (&iter, actors);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &actor, NULL))
|
||||
{
|
||||
ClutterRequestMode request_mode;
|
||||
|
||||
g_assert (actor != NULL);
|
||||
|
||||
request_mode = clutter_actor_get_request_mode (actor);
|
||||
|
||||
if (request_mode == CLUTTER_REQUEST_CONTENT_SIZE)
|
||||
_clutter_actor_queue_only_relayout (actor);
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* _clutter_content_attached:
|
||||
* @content: a #ClutterContent
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Attaches @actor to the @content.
|
||||
*
|
||||
* This function should be used internally every time a #ClutterActor
|
||||
* is associated to a #ClutterContent, to set up a backpointer from
|
||||
* the @content to the @actor.
|
||||
*
|
||||
* This function will invoke the [vfunc@Clutter.Content.attached] virtual
|
||||
* function.
|
||||
*/
|
||||
void
|
||||
_clutter_content_attached (ClutterContent *content,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
GObject *obj = G_OBJECT (content);
|
||||
GHashTable *actors;
|
||||
|
||||
actors = g_object_get_qdata (obj, quark_content_actors);
|
||||
if (actors == NULL)
|
||||
{
|
||||
actors = g_hash_table_new (NULL, NULL);
|
||||
g_object_set_qdata_full (obj, quark_content_actors,
|
||||
actors,
|
||||
(GDestroyNotify) g_hash_table_unref);
|
||||
}
|
||||
|
||||
g_hash_table_insert (actors, actor, actor);
|
||||
|
||||
g_signal_emit (content, content_signals[ATTACHED], 0, actor);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* _clutter_content_detached:
|
||||
* @content: a #ClutterContent
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Detaches @actor from @content.
|
||||
*
|
||||
* This function should be used internally every time a #ClutterActor
|
||||
* removes the association with a #ClutterContent.
|
||||
*
|
||||
* This function will invoke the [vfunc@Clutter.Content.detached] virtual
|
||||
* function.
|
||||
*/
|
||||
void
|
||||
_clutter_content_detached (ClutterContent *content,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
GObject *obj = G_OBJECT (content);
|
||||
GHashTable *actors;
|
||||
|
||||
actors = g_object_get_qdata (obj, quark_content_actors);
|
||||
g_assert (actors != NULL);
|
||||
|
||||
g_hash_table_remove (actors, actor);
|
||||
|
||||
if (g_hash_table_size (actors) == 0)
|
||||
g_object_set_qdata (obj, quark_content_actors, NULL);
|
||||
|
||||
g_signal_emit (content, content_signals[DETACHED], 0, actor);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* _clutter_content_paint_content:
|
||||
* @content: a #ClutterContent
|
||||
* @actor: a #ClutterActor
|
||||
* @node: a #ClutterPaintNode
|
||||
* @paint_context: a #ClutterPaintContext
|
||||
*
|
||||
* Creates the render tree for the @content and @actor.
|
||||
*
|
||||
* This function will invoke the [vfunc@Clutter.Content.paint_content]
|
||||
* virtual function.
|
||||
*/
|
||||
void
|
||||
_clutter_content_paint_content (ClutterContent *content,
|
||||
ClutterActor *actor,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node,
|
||||
paint_context);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_content_get_preferred_size:
|
||||
* @content: a #ClutterContent
|
||||
* @width: (out) (optional): return location for the natural width of the content
|
||||
* @height: (out) (optional): return location for the natural height of the content
|
||||
*
|
||||
* Retrieves the natural size of the @content, if any.
|
||||
*
|
||||
* The natural size of a #ClutterContent is defined as the size the content
|
||||
* would have regardless of the allocation of the actor that is painting it,
|
||||
* for instance the size of an image data.
|
||||
*
|
||||
* Return value: %TRUE if the content has a preferred size, and %FALSE
|
||||
* otherwise
|
||||
*/
|
||||
gboolean
|
||||
clutter_content_get_preferred_size (ClutterContent *content,
|
||||
gfloat *width,
|
||||
gfloat *height)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_CONTENT (content), FALSE);
|
||||
|
||||
return CLUTTER_CONTENT_GET_IFACE (content)->get_preferred_size (content,
|
||||
width,
|
||||
height);
|
||||
}
|
90
mutter/clutter/clutter/clutter-content.h
Normal file
90
mutter/clutter/clutter/clutter-content.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2012 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_CONTENT (clutter_content_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_INTERFACE (ClutterContent, clutter_content, CLUTTER, CONTENT, GObject)
|
||||
|
||||
/**
|
||||
* ClutterContentInterface:
|
||||
* @get_preferred_size: virtual function; should be overridden by subclasses
|
||||
* of #ClutterContent that have a natural size
|
||||
* @paint_content: virtual function; called each time the content needs to
|
||||
* paint itself
|
||||
* @attached: virtual function; called each time a #ClutterContent is attached
|
||||
* to a #ClutterActor.
|
||||
* @detached: virtual function; called each time a #ClutterContent is detached
|
||||
* from a #ClutterActor.
|
||||
* @invalidate: virtual function; called each time a #ClutterContent state
|
||||
* is changed.
|
||||
*
|
||||
* The #ClutterContentInterface structure contains only
|
||||
* private data.
|
||||
*/
|
||||
struct _ClutterContentInterface
|
||||
{
|
||||
/*< private >*/
|
||||
GTypeInterface g_iface;
|
||||
|
||||
/*< public >*/
|
||||
gboolean (* get_preferred_size) (ClutterContent *content,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
void (* paint_content) (ClutterContent *content,
|
||||
ClutterActor *actor,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context);
|
||||
|
||||
void (* attached) (ClutterContent *content,
|
||||
ClutterActor *actor);
|
||||
void (* detached) (ClutterContent *content,
|
||||
ClutterActor *actor);
|
||||
|
||||
void (* invalidate) (ClutterContent *content);
|
||||
|
||||
void (* invalidate_size) (ClutterContent *content);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_content_get_preferred_size (ClutterContent *content,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_content_invalidate (ClutterContent *content);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_content_invalidate_size (ClutterContent *content);
|
||||
|
||||
G_END_DECLS
|
48
mutter/clutter/clutter/clutter-context-private.h
Normal file
48
mutter/clutter/clutter/clutter-context-private.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
* Copyright (C) 2023 Red Hat
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-context.h"
|
||||
|
||||
struct _ClutterContext
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
ClutterBackend *backend;
|
||||
ClutterStageManager *stage_manager;
|
||||
|
||||
GAsyncQueue *events_queue;
|
||||
|
||||
/* the event filters added via clutter_event_add_filter. these are
|
||||
* ordered from least recently added to most recently added */
|
||||
GList *event_filters;
|
||||
|
||||
CoglPangoFontMap *font_map;
|
||||
|
||||
GSList *current_event;
|
||||
|
||||
GList *repaint_funcs;
|
||||
guint last_repaint_id;
|
||||
|
||||
ClutterSettings *settings;
|
||||
|
||||
gboolean is_initialized;
|
||||
gboolean show_fps;
|
||||
};
|
319
mutter/clutter/clutter/clutter-context.c
Normal file
319
mutter/clutter/clutter/clutter-context.c
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-context-private.h"
|
||||
|
||||
#include <hb-glib.h>
|
||||
|
||||
#include "cally/cally.h"
|
||||
#include "clutter/clutter-backend-private.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-graphene.h"
|
||||
#include "clutter/clutter-main.h"
|
||||
#include "clutter/clutter-paint-node-private.h"
|
||||
#include "clutter/clutter-settings-private.h"
|
||||
|
||||
static gboolean clutter_disable_mipmap_text = FALSE;
|
||||
static gboolean clutter_show_fps = FALSE;
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
static const GDebugKey clutter_debug_keys[] = {
|
||||
{ "misc", CLUTTER_DEBUG_MISC },
|
||||
{ "actor", CLUTTER_DEBUG_ACTOR },
|
||||
{ "texture", CLUTTER_DEBUG_TEXTURE },
|
||||
{ "event", CLUTTER_DEBUG_EVENT },
|
||||
{ "paint", CLUTTER_DEBUG_PAINT },
|
||||
{ "pick", CLUTTER_DEBUG_PICK },
|
||||
{ "pango", CLUTTER_DEBUG_PANGO },
|
||||
{ "backend", CLUTTER_DEBUG_BACKEND },
|
||||
{ "scheduler", CLUTTER_DEBUG_SCHEDULER },
|
||||
{ "script", CLUTTER_DEBUG_SCRIPT },
|
||||
{ "shader", CLUTTER_DEBUG_SHADER },
|
||||
{ "animation", CLUTTER_DEBUG_ANIMATION },
|
||||
{ "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 },
|
||||
{ "grabs", CLUTTER_DEBUG_GRABS },
|
||||
{ "frame-clock", CLUTTER_DEBUG_FRAME_CLOCK },
|
||||
{ "gestures", CLUTTER_DEBUG_GESTURES },
|
||||
};
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
static const GDebugKey clutter_pick_debug_keys[] = {
|
||||
{ "nop-picking", CLUTTER_DEBUG_NOP_PICKING },
|
||||
};
|
||||
|
||||
static const GDebugKey clutter_paint_debug_keys[] = {
|
||||
{ "disable-swap-events", CLUTTER_DEBUG_DISABLE_SWAP_EVENTS },
|
||||
{ "disable-clipped-redraws", CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS },
|
||||
{ "redraws", CLUTTER_DEBUG_REDRAWS },
|
||||
{ "paint-volumes", CLUTTER_DEBUG_PAINT_VOLUMES },
|
||||
{ "disable-culling", CLUTTER_DEBUG_DISABLE_CULLING },
|
||||
{ "disable-offscreen-redirect", CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT },
|
||||
{ "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 },
|
||||
};
|
||||
|
||||
typedef struct _ClutterContextPrivate
|
||||
{
|
||||
ClutterTextDirection text_direction;
|
||||
} ClutterContextPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterContext, clutter_context, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
clutter_context_dispose (GObject *object)
|
||||
{
|
||||
ClutterContext *context = CLUTTER_CONTEXT (object);
|
||||
|
||||
g_clear_pointer (&context->events_queue, g_async_queue_unref);
|
||||
g_clear_pointer (&context->backend, clutter_backend_destroy);
|
||||
|
||||
G_OBJECT_CLASS (clutter_context_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_context_class_init (ClutterContextClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = clutter_context_dispose;
|
||||
|
||||
clutter_graphene_init ();
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_context_init (ClutterContext *context)
|
||||
{
|
||||
ClutterContextPrivate *priv = clutter_context_get_instance_private (context);
|
||||
|
||||
priv->text_direction = CLUTTER_TEXT_DIRECTION_LTR;
|
||||
}
|
||||
|
||||
ClutterTextDirection
|
||||
clutter_get_text_direction (void)
|
||||
{
|
||||
ClutterTextDirection dir = CLUTTER_TEXT_DIRECTION_LTR;
|
||||
const gchar *direction;
|
||||
|
||||
direction = g_getenv ("CLUTTER_TEXT_DIRECTION");
|
||||
if (direction && *direction != '\0')
|
||||
{
|
||||
if (strcmp (direction, "rtl") == 0)
|
||||
dir = CLUTTER_TEXT_DIRECTION_RTL;
|
||||
else if (strcmp (direction, "ltr") == 0)
|
||||
dir = CLUTTER_TEXT_DIRECTION_LTR;
|
||||
}
|
||||
else
|
||||
{
|
||||
PangoLanguage *language;
|
||||
const PangoScript *scripts;
|
||||
int n_scripts, i;
|
||||
|
||||
language = pango_language_get_default ();
|
||||
scripts = pango_language_get_scripts (language, &n_scripts);
|
||||
|
||||
for (i = 0; i < n_scripts; i++)
|
||||
{
|
||||
hb_script_t script;
|
||||
hb_direction_t text_dir;
|
||||
|
||||
script = hb_glib_script_to_script ((GUnicodeScript) scripts[i]);
|
||||
text_dir = hb_script_get_horizontal_direction (script);
|
||||
|
||||
if (text_dir == HB_DIRECTION_LTR)
|
||||
dir = CLUTTER_TEXT_DIRECTION_LTR;
|
||||
else if (text_dir == HB_DIRECTION_RTL)
|
||||
dir = CLUTTER_TEXT_DIRECTION_RTL;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (MISC, "Text direction: %s",
|
||||
dir == CLUTTER_TEXT_DIRECTION_RTL ? "rtl" : "ltr");
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_context_init_real (ClutterContext *context,
|
||||
ClutterContextFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
ClutterContextPrivate *priv = clutter_context_get_instance_private (context);
|
||||
|
||||
/* If we are displaying the regions that would get redrawn with clipped
|
||||
* redraws enabled we actually have to disable the clipped redrawing
|
||||
* because otherwise we end up with nasty trails of rectangles everywhere.
|
||||
*/
|
||||
if (clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)
|
||||
clutter_paint_debug_flags |= CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS;
|
||||
|
||||
/* The same is true when drawing the outlines of paint volumes... */
|
||||
if (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES)
|
||||
{
|
||||
clutter_paint_debug_flags |=
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS | CLUTTER_DEBUG_DISABLE_CULLING;
|
||||
}
|
||||
|
||||
if (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)
|
||||
g_message ("Enabling damaged region");
|
||||
|
||||
if (!_clutter_backend_create_context (context->backend, error))
|
||||
return FALSE;
|
||||
|
||||
priv->text_direction = clutter_get_text_direction ();
|
||||
|
||||
context->is_initialized = TRUE;
|
||||
|
||||
/* Initialize a11y */
|
||||
if (!(flags & CLUTTER_CONTEXT_FLAG_NO_A11Y))
|
||||
cally_accessibility_init ();
|
||||
|
||||
/* Initialize types required for paint nodes */
|
||||
clutter_paint_node_init_types (context->backend);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
init_clutter_debug (ClutterContext *context)
|
||||
{
|
||||
const char *env_string;
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
env_string = g_getenv ("CLUTTER_DEBUG");
|
||||
if (env_string != NULL)
|
||||
{
|
||||
clutter_debug_flags =
|
||||
g_parse_debug_string (env_string,
|
||||
clutter_debug_keys,
|
||||
G_N_ELEMENTS (clutter_debug_keys));
|
||||
env_string = NULL;
|
||||
}
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
env_string = g_getenv ("CLUTTER_PICK");
|
||||
if (env_string != NULL)
|
||||
{
|
||||
clutter_pick_debug_flags =
|
||||
g_parse_debug_string (env_string,
|
||||
clutter_pick_debug_keys,
|
||||
G_N_ELEMENTS (clutter_pick_debug_keys));
|
||||
env_string = NULL;
|
||||
}
|
||||
|
||||
env_string = g_getenv ("CLUTTER_PAINT");
|
||||
if (env_string != NULL)
|
||||
{
|
||||
clutter_paint_debug_flags =
|
||||
g_parse_debug_string (env_string,
|
||||
clutter_paint_debug_keys,
|
||||
G_N_ELEMENTS (clutter_paint_debug_keys));
|
||||
env_string = NULL;
|
||||
}
|
||||
|
||||
env_string = g_getenv ("CLUTTER_SHOW_FPS");
|
||||
if (env_string)
|
||||
clutter_show_fps = TRUE;
|
||||
|
||||
env_string = g_getenv ("CLUTTER_DISABLE_MIPMAPPED_TEXT");
|
||||
if (env_string)
|
||||
clutter_disable_mipmap_text = TRUE;
|
||||
}
|
||||
|
||||
ClutterContext *
|
||||
clutter_context_new (ClutterContextFlags flags,
|
||||
ClutterBackendConstructor backend_constructor,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
ClutterContext *context;
|
||||
|
||||
context = g_object_new (CLUTTER_TYPE_CONTEXT, NULL);
|
||||
|
||||
init_clutter_debug (context);
|
||||
context->show_fps = clutter_show_fps;
|
||||
context->is_initialized = FALSE;
|
||||
|
||||
context->backend = backend_constructor (user_data);
|
||||
context->settings = clutter_settings_get_default ();
|
||||
_clutter_settings_set_backend (context->settings,
|
||||
context->backend);
|
||||
|
||||
context->events_queue =
|
||||
g_async_queue_new_full ((GDestroyNotify) clutter_event_free);
|
||||
context->last_repaint_id = 1;
|
||||
|
||||
if (!clutter_context_init_real (context, flags, error))
|
||||
return NULL;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_context_destroy (ClutterContext *context)
|
||||
{
|
||||
g_object_run_dispose (G_OBJECT (context));
|
||||
g_object_unref (context);
|
||||
}
|
||||
|
||||
ClutterBackend *
|
||||
clutter_context_get_backend (ClutterContext *context)
|
||||
{
|
||||
return context->backend;
|
||||
}
|
||||
|
||||
CoglPangoFontMap *
|
||||
clutter_context_get_pango_fontmap (ClutterContext *context)
|
||||
{
|
||||
CoglPangoFontMap *font_map;
|
||||
gdouble resolution;
|
||||
gboolean use_mipmapping;
|
||||
|
||||
if (G_LIKELY (context->font_map != NULL))
|
||||
return context->font_map;
|
||||
|
||||
font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new ());
|
||||
|
||||
resolution = clutter_backend_get_resolution (context->backend);
|
||||
cogl_pango_font_map_set_resolution (font_map, resolution);
|
||||
|
||||
use_mipmapping = !clutter_disable_mipmap_text;
|
||||
cogl_pango_font_map_set_use_mipmapping (font_map, use_mipmapping);
|
||||
|
||||
context->font_map = font_map;
|
||||
|
||||
return context->font_map;
|
||||
}
|
||||
|
||||
ClutterTextDirection
|
||||
clutter_context_get_text_direction (ClutterContext *context)
|
||||
{
|
||||
ClutterContextPrivate *priv = clutter_context_get_instance_private (context);
|
||||
|
||||
return priv->text_direction;
|
||||
}
|
67
mutter/clutter/clutter/clutter-context.h
Normal file
67
mutter/clutter/clutter/clutter-context.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
* Copyright (C) 2023 Red Hat
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-settings.h"
|
||||
#include "cogl-pango/cogl-pango.h"
|
||||
|
||||
typedef enum _ClutterContextFlags
|
||||
{
|
||||
CLUTTER_CONTEXT_FLAG_NONE = 0,
|
||||
CLUTTER_CONTEXT_FLAG_NO_A11Y = 1 << 0,
|
||||
} ClutterContextFlags;
|
||||
|
||||
typedef ClutterBackend * (* ClutterBackendConstructor) (gpointer user_data);
|
||||
|
||||
#define CLUTTER_TYPE_CONTEXT (clutter_context_get_type ())
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ClutterContext, clutter_context,
|
||||
CLUTTER, CONTEXT, GObject)
|
||||
|
||||
/**
|
||||
* clutter_context_new: (skip)
|
||||
*/
|
||||
ClutterContext * clutter_context_new (ClutterContextFlags flags,
|
||||
ClutterBackendConstructor backend_constructor,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* clutter_context_destroy: (skip)
|
||||
*/
|
||||
CLUTTER_EXPORT
|
||||
void clutter_context_destroy (ClutterContext *context);
|
||||
|
||||
/**
|
||||
* clutter_context_get_backend:
|
||||
*
|
||||
* Returns: (transfer none): The %ClutterBackend
|
||||
*/
|
||||
CLUTTER_EXPORT
|
||||
ClutterBackend * clutter_context_get_backend (ClutterContext *context);
|
||||
|
||||
/**
|
||||
* clutter_context_get_pango_fontmap: (skip)
|
||||
*/
|
||||
CoglPangoFontMap * clutter_context_get_pango_fontmap (ClutterContext *context);
|
||||
|
||||
ClutterTextDirection clutter_context_get_text_direction (ClutterContext *context);
|
92
mutter/clutter/clutter/clutter-damage-history.c
Normal file
92
mutter/clutter/clutter/clutter-damage-history.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
|
||||
* Copyright (C) 2020 Red Hat Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-damage-history.h"
|
||||
|
||||
#define DAMAGE_HISTORY_LENGTH 0x10
|
||||
|
||||
struct _ClutterDamageHistory
|
||||
{
|
||||
MtkRegion *damages[DAMAGE_HISTORY_LENGTH];
|
||||
int index;
|
||||
};
|
||||
|
||||
ClutterDamageHistory *
|
||||
clutter_damage_history_new (void)
|
||||
{
|
||||
ClutterDamageHistory *history;
|
||||
|
||||
history = g_new0 (ClutterDamageHistory, 1);
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_damage_history_free (ClutterDamageHistory *history)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (history->damages); i++)
|
||||
g_clear_pointer (&history->damages[i], mtk_region_unref);
|
||||
|
||||
g_free (history);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
|
||||
int age)
|
||||
{
|
||||
if (age >= DAMAGE_HISTORY_LENGTH ||
|
||||
age < 1)
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_damage_history_lookup (history, age))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_damage_history_record (ClutterDamageHistory *history,
|
||||
const MtkRegion *damage)
|
||||
{
|
||||
g_clear_pointer (&history->damages[history->index], mtk_region_unref);
|
||||
history->damages[history->index] = mtk_region_copy (damage);
|
||||
}
|
||||
|
||||
static inline int
|
||||
step_damage_index (int current,
|
||||
int diff)
|
||||
{
|
||||
return (current + diff) & (DAMAGE_HISTORY_LENGTH - 1);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_damage_history_step (ClutterDamageHistory *history)
|
||||
{
|
||||
history->index = step_damage_index (history->index, 1);
|
||||
}
|
||||
|
||||
const MtkRegion *
|
||||
clutter_damage_history_lookup (ClutterDamageHistory *history,
|
||||
int age)
|
||||
{
|
||||
return history->damages[step_damage_index (history->index, -age)];
|
||||
}
|
47
mutter/clutter/clutter/clutter-damage-history.h
Normal file
47
mutter/clutter/clutter/clutter-damage-history.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "clutter/clutter-macros.h"
|
||||
#include "mtk/mtk.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 MtkRegion *damage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_step (ClutterDamageHistory *history);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
const MtkRegion * clutter_damage_history_lookup (ClutterDamageHistory *history,
|
||||
int age);
|
51
mutter/clutter/clutter/clutter-debug.h
Normal file
51
mutter/clutter/clutter/clutter-debug.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "clutter/clutter-main.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
|
||||
#define CLUTTER_HAS_DEBUG(type) ((clutter_debug_flags & CLUTTER_DEBUG_##type) != FALSE)
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
/* Try the GCC extension for valists in macros */
|
||||
#define CLUTTER_NOTE(type,x,a...) G_STMT_START { \
|
||||
if (G_UNLIKELY (CLUTTER_HAS_DEBUG (type))) { \
|
||||
_clutter_debug_message ("[" #type "]: " x, ##a); \
|
||||
} } G_STMT_END
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
/* Try the C99 version; unfortunately, this does not allow us to pass
|
||||
* empty arguments to the macro, which means we have to
|
||||
* do an intemediate printf.
|
||||
*/
|
||||
#define CLUTTER_NOTE(type,...) G_STMT_START { \
|
||||
if (G_UNLIKELY (CLUTTER_HAS_DEBUG (type))) { \
|
||||
gchar *_fmt = g_strdup_printf (__VA_ARGS__); \
|
||||
_clutter_debug_message ("[" #type "]: %s", _fmt); \
|
||||
g_free (_fmt); \
|
||||
} } G_STMT_END
|
||||
#endif
|
||||
|
||||
#else /* !CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
#define CLUTTER_NOTE(type,...) G_STMT_START { } G_STMT_END
|
||||
#define CLUTTER_HAS_DEBUG(type) FALSE
|
||||
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
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);
|
||||
void _clutter_debug_message (const char *format,
|
||||
...) G_GNUC_PRINTF (1, 2);
|
||||
|
||||
G_END_DECLS
|
804
mutter/clutter/clutter/clutter-deform-effect.c
Normal file
804
mutter/clutter/clutter/clutter-deform-effect.c
Normal file
@ -0,0 +1,804 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Based on the MxDeformTexture class, written by:
|
||||
* Chris Lord <chris@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterDeformEffect:
|
||||
*
|
||||
* A base class for effects deforming the geometry of an actor
|
||||
*
|
||||
* #ClutterDeformEffect is an abstract class providing all the plumbing
|
||||
* for creating effects that result in the deformation of an actor's
|
||||
* geometry.
|
||||
*
|
||||
* #ClutterDeformEffect uses offscreen buffers to render the contents of
|
||||
* a #ClutterActor and then the Cogl vertex buffers API to submit the
|
||||
* geometry to the GPU.
|
||||
*
|
||||
* ## Implementing ClutterDeformEffect
|
||||
*
|
||||
* Sub-classes of #ClutterDeformEffect should override the
|
||||
* [vfunc@Clutter.DeformEffect.deform_vertex] virtual function; this function
|
||||
* is called on every vertex that needs to be deformed by the effect.
|
||||
* Each passed vertex is an in-out parameter that initially contains the
|
||||
* position of the vertex and should be modified according to a specific
|
||||
* deformation algorithm.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-deform-effect.h"
|
||||
#include "clutter/clutter-color.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-paint-node.h"
|
||||
#include "clutter/clutter-paint-nodes.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
#define DEFAULT_N_TILES 32
|
||||
|
||||
typedef struct _ClutterDeformEffectPrivate
|
||||
{
|
||||
CoglPipeline *back_pipeline;
|
||||
|
||||
gint x_tiles;
|
||||
gint y_tiles;
|
||||
|
||||
CoglAttributeBuffer *buffer;
|
||||
|
||||
CoglPrimitive *primitive;
|
||||
|
||||
CoglPrimitive *lines_primitive;
|
||||
|
||||
gint n_vertices;
|
||||
|
||||
gulong allocation_id;
|
||||
|
||||
guint is_dirty : 1;
|
||||
} ClutterDeformEffectPrivate;
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_X_TILES,
|
||||
PROP_Y_TILES,
|
||||
|
||||
PROP_BACK_MATERIAL,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterDeformEffect,
|
||||
clutter_deform_effect,
|
||||
CLUTTER_TYPE_OFFSCREEN_EFFECT)
|
||||
|
||||
static void
|
||||
clutter_deform_effect_real_deform_vertex (ClutterDeformEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height,
|
||||
CoglTextureVertex *vertex)
|
||||
{
|
||||
g_warning ("%s: Deformation effect of type '%s' does not implement "
|
||||
"the required ClutterDeformEffect::deform_vertex virtual "
|
||||
"function.",
|
||||
G_STRLOC,
|
||||
G_OBJECT_TYPE_NAME (effect));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height,
|
||||
CoglTextureVertex *vertex)
|
||||
{
|
||||
CLUTTER_DEFORM_EFFECT_GET_CLASS (effect)->deform_vertex (effect,
|
||||
width, height,
|
||||
vertex);
|
||||
}
|
||||
|
||||
static void
|
||||
vbo_invalidate (ClutterActor *actor,
|
||||
GParamSpec *pspec,
|
||||
ClutterDeformEffect *effect)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (effect);
|
||||
|
||||
priv->is_dirty = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_set_actor (ClutterActorMeta *meta,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterDeformEffect *effect = CLUTTER_DEFORM_EFFECT (meta);
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (effect);
|
||||
|
||||
if (priv->allocation_id != 0)
|
||||
{
|
||||
ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
|
||||
|
||||
if (old_actor != NULL)
|
||||
g_clear_signal_handler (&priv->allocation_id, old_actor);
|
||||
|
||||
priv->allocation_id = 0;
|
||||
}
|
||||
|
||||
/* we need to invalidate the VBO whenever the allocation of the actor
|
||||
* changes
|
||||
*/
|
||||
if (actor != NULL)
|
||||
priv->allocation_id = g_signal_connect (actor, "notify::allocation",
|
||||
G_CALLBACK (vbo_invalidate),
|
||||
meta);
|
||||
|
||||
priv->is_dirty = TRUE;
|
||||
|
||||
CLUTTER_ACTOR_META_CLASS (clutter_deform_effect_parent_class)->set_actor (meta, actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (effect);
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (self);
|
||||
CoglPipeline *pipeline;
|
||||
CoglDepthState depth_state;
|
||||
|
||||
if (priv->is_dirty)
|
||||
{
|
||||
gboolean mapped_buffer;
|
||||
CoglVertexP3T2C4 *verts;
|
||||
ClutterActor *actor;
|
||||
gfloat width, height;
|
||||
guint opacity;
|
||||
gint i, j;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
opacity = clutter_actor_get_paint_opacity (actor);
|
||||
|
||||
/* 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))
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
|
||||
/* XXX ideally, the sub-classes should tell us what they
|
||||
* changed in the texture vertices; we then would be able to
|
||||
* avoid resubmitting the same data, if it did not change. for
|
||||
* the time being, we resubmit everything
|
||||
*/
|
||||
verts = cogl_buffer_map (COGL_BUFFER (priv->buffer),
|
||||
COGL_BUFFER_ACCESS_WRITE,
|
||||
COGL_BUFFER_MAP_HINT_DISCARD);
|
||||
|
||||
/* If the map failed then we'll resort to allocating a temporary
|
||||
buffer */
|
||||
if (verts == NULL)
|
||||
{
|
||||
mapped_buffer = FALSE;
|
||||
verts = g_malloc (sizeof (*verts) * priv->n_vertices);
|
||||
}
|
||||
else
|
||||
mapped_buffer = TRUE;
|
||||
|
||||
for (i = 0; i < priv->y_tiles + 1; i++)
|
||||
{
|
||||
for (j = 0; j < priv->x_tiles + 1; j++)
|
||||
{
|
||||
CoglVertexP3T2C4 *vertex_out;
|
||||
CoglTextureVertex vertex;
|
||||
|
||||
/* CoglTextureVertex isn't an ideal structure to use for
|
||||
this because it contains a CoglColor. The internal
|
||||
layout of CoglColor is mean to be private so Clutter
|
||||
can not pass a pointer to it as a vertex
|
||||
attribute. Also it contains padding so we end up
|
||||
storing more data in the vertex buffer than we need
|
||||
to. Instead we let the application modify a dummy
|
||||
vertex and then copy the details back out to a more
|
||||
well-defined struct */
|
||||
|
||||
vertex.tx = (float) j / priv->x_tiles;
|
||||
vertex.ty = (float) i / priv->y_tiles;
|
||||
|
||||
vertex.x = width * vertex.tx;
|
||||
vertex.y = height * vertex.ty;
|
||||
vertex.z = 0.0f;
|
||||
|
||||
cogl_color_init_from_4f (&vertex.color, 1.0, 1.0, 1.0, opacity / 255.0);
|
||||
|
||||
clutter_deform_effect_deform_vertex (self,
|
||||
width, height,
|
||||
&vertex);
|
||||
|
||||
vertex_out = verts + i * (priv->x_tiles + 1) + j;
|
||||
|
||||
vertex_out->x = vertex.x;
|
||||
vertex_out->y = vertex.y;
|
||||
vertex_out->z = vertex.z;
|
||||
vertex_out->s = vertex.tx;
|
||||
vertex_out->t = vertex.ty;
|
||||
vertex_out->r = cogl_color_get_red (&vertex.color) * 255.0;
|
||||
vertex_out->g = cogl_color_get_green (&vertex.color) * 255.0;
|
||||
vertex_out->b = cogl_color_get_blue (&vertex.color) * 255.0;
|
||||
vertex_out->a = cogl_color_get_alpha (&vertex.color) * 255.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapped_buffer)
|
||||
cogl_buffer_unmap (COGL_BUFFER (priv->buffer));
|
||||
else
|
||||
{
|
||||
cogl_buffer_set_data (COGL_BUFFER (priv->buffer),
|
||||
0, /* offset */
|
||||
verts,
|
||||
sizeof (*verts) * priv->n_vertices);
|
||||
g_free (verts);
|
||||
}
|
||||
|
||||
priv->is_dirty = FALSE;
|
||||
}
|
||||
|
||||
pipeline = clutter_offscreen_effect_get_pipeline (effect);
|
||||
|
||||
/* enable depth testing */
|
||||
cogl_depth_state_init (&depth_state);
|
||||
cogl_depth_state_set_test_enabled (&depth_state, TRUE);
|
||||
cogl_depth_state_set_test_function (&depth_state, COGL_DEPTH_TEST_FUNCTION_LEQUAL);
|
||||
cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL);
|
||||
|
||||
/* enable backface culling if we have a back material */
|
||||
if (priv->back_pipeline != NULL)
|
||||
cogl_pipeline_set_cull_face_mode (pipeline,
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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
|
||||
instead we make a temporary copy */
|
||||
back_pipeline = cogl_pipeline_copy (priv->back_pipeline);
|
||||
cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL);
|
||||
cogl_pipeline_set_cull_face_mode (back_pipeline,
|
||||
COGL_PIPELINE_CULL_FACE_MODE_FRONT);
|
||||
|
||||
|
||||
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);
|
||||
g_object_unref (back_pipeline);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (priv->lines_primitive != NULL))
|
||||
{
|
||||
static ClutterColor red = CLUTTER_COLOR_INIT (255, 0, 0, 255);
|
||||
ClutterPaintNode *lines_node;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_deform_effect_free_arrays (ClutterDeformEffect *self)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->buffer);
|
||||
g_clear_object (&priv->primitive);
|
||||
g_clear_object (&priv->lines_primitive);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_init_arrays (ClutterDeformEffect *self)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (self);
|
||||
gint x, y, direction, n_indices;
|
||||
CoglAttribute *attributes[3];
|
||||
guint16 *static_indices;
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglIndices *indices;
|
||||
guint16 *idx;
|
||||
int i;
|
||||
|
||||
clutter_deform_effect_free_arrays (self);
|
||||
|
||||
n_indices = ((2 + 2 * priv->x_tiles)
|
||||
* priv->y_tiles
|
||||
+ (priv->y_tiles - 1));
|
||||
|
||||
static_indices = g_new (guint16, n_indices);
|
||||
|
||||
#define MESH_INDEX(x,y) ((y) * (priv->x_tiles + 1) + (x))
|
||||
|
||||
/* compute all the triangles from the various tiles */
|
||||
direction = 1;
|
||||
|
||||
idx = static_indices;
|
||||
idx[0] = MESH_INDEX (0, 0);
|
||||
idx[1] = MESH_INDEX (0, 1);
|
||||
idx += 2;
|
||||
|
||||
for (y = 0; y < priv->y_tiles; y++)
|
||||
{
|
||||
for (x = 0; x < priv->x_tiles; x++)
|
||||
{
|
||||
if (direction)
|
||||
{
|
||||
idx[0] = MESH_INDEX (x + 1, y);
|
||||
idx[1] = MESH_INDEX (x + 1, y + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
idx[0] = MESH_INDEX (priv->x_tiles - x - 1, y);
|
||||
idx[1] = MESH_INDEX (priv->x_tiles - x - 1, y + 1);
|
||||
}
|
||||
|
||||
idx += 2;
|
||||
}
|
||||
|
||||
if (y == (priv->y_tiles - 1))
|
||||
break;
|
||||
|
||||
if (direction)
|
||||
{
|
||||
idx[0] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
idx[1] = MESH_INDEX (priv->x_tiles, y + 1);
|
||||
idx[2] = MESH_INDEX (priv->x_tiles, y + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
idx[0] = MESH_INDEX (0, y + 1);
|
||||
idx[1] = MESH_INDEX (0, y + 1);
|
||||
idx[2] = MESH_INDEX (0, y + 2);
|
||||
}
|
||||
|
||||
idx += 3;
|
||||
|
||||
direction = !direction;
|
||||
}
|
||||
|
||||
#undef MESH_INDEX
|
||||
|
||||
indices = cogl_indices_new (ctx,
|
||||
COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
static_indices,
|
||||
n_indices);
|
||||
|
||||
g_free (static_indices);
|
||||
|
||||
priv->n_vertices = (priv->x_tiles + 1) * (priv->y_tiles + 1);
|
||||
|
||||
priv->buffer =
|
||||
cogl_attribute_buffer_new (ctx,
|
||||
sizeof (CoglVertexP3T2C4) *
|
||||
priv->n_vertices,
|
||||
NULL);
|
||||
|
||||
/* The application is expected to continuously modify the vertices
|
||||
so we should give a hint to Cogl about that */
|
||||
cogl_buffer_set_update_hint (COGL_BUFFER (priv->buffer),
|
||||
COGL_BUFFER_UPDATE_HINT_DYNAMIC);
|
||||
|
||||
attributes[0] = cogl_attribute_new (priv->buffer,
|
||||
"cogl_position_in",
|
||||
sizeof (CoglVertexP3T2C4),
|
||||
G_STRUCT_OFFSET (CoglVertexP3T2C4, x),
|
||||
3, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT);
|
||||
attributes[1] = cogl_attribute_new (priv->buffer,
|
||||
"cogl_tex_coord0_in",
|
||||
sizeof (CoglVertexP3T2C4),
|
||||
G_STRUCT_OFFSET (CoglVertexP3T2C4, s),
|
||||
2, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT);
|
||||
attributes[2] = cogl_attribute_new (priv->buffer,
|
||||
"cogl_color_in",
|
||||
sizeof (CoglVertexP3T2C4),
|
||||
G_STRUCT_OFFSET (CoglVertexP3T2C4, r),
|
||||
4, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
|
||||
|
||||
priv->primitive =
|
||||
cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLE_STRIP,
|
||||
priv->n_vertices,
|
||||
attributes,
|
||||
3 /* n_attributes */);
|
||||
cogl_primitive_set_indices (priv->primitive,
|
||||
indices,
|
||||
n_indices);
|
||||
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DEFORM_TILES))
|
||||
{
|
||||
priv->lines_primitive =
|
||||
cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP,
|
||||
priv->n_vertices,
|
||||
attributes,
|
||||
2 /* n_attributes */);
|
||||
cogl_primitive_set_indices (priv->lines_primitive,
|
||||
indices,
|
||||
n_indices);
|
||||
}
|
||||
|
||||
g_object_unref (indices);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
g_object_unref (attributes[i]);
|
||||
|
||||
priv->is_dirty = TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_deform_effect_free_back_pipeline (ClutterDeformEffect *self)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->back_pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject);
|
||||
|
||||
clutter_deform_effect_free_arrays (self);
|
||||
clutter_deform_effect_free_back_pipeline (self);
|
||||
|
||||
G_OBJECT_CLASS (clutter_deform_effect_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterDeformEffect *self = CLUTTER_DEFORM_EFFECT (gobject);
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_X_TILES:
|
||||
clutter_deform_effect_set_n_tiles (self, g_value_get_uint (value),
|
||||
priv->y_tiles);
|
||||
break;
|
||||
|
||||
case PROP_Y_TILES:
|
||||
clutter_deform_effect_set_n_tiles (self, priv->x_tiles,
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_BACK_MATERIAL:
|
||||
clutter_deform_effect_set_back_material (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterDeformEffect *effect = CLUTTER_DEFORM_EFFECT (gobject);
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (effect);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_X_TILES:
|
||||
g_value_set_uint (value, priv->x_tiles);
|
||||
break;
|
||||
|
||||
case PROP_Y_TILES:
|
||||
g_value_set_uint (value, priv->y_tiles);
|
||||
break;
|
||||
|
||||
case PROP_BACK_MATERIAL:
|
||||
g_value_set_object (value, priv->back_pipeline);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_class_init (ClutterDeformEffectClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
ClutterOffscreenEffectClass *offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
|
||||
klass->deform_vertex = clutter_deform_effect_real_deform_vertex;
|
||||
|
||||
/**
|
||||
* ClutterDeformEffect:x-tiles:
|
||||
*
|
||||
* The number of horizontal tiles. The bigger the number, the
|
||||
* smaller the tiles
|
||||
*/
|
||||
obj_props[PROP_X_TILES] =
|
||||
g_param_spec_uint ("x-tiles", NULL, NULL,
|
||||
1, G_MAXUINT,
|
||||
DEFAULT_N_TILES,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterDeformEffect:y-tiles:
|
||||
*
|
||||
* The number of vertical tiles. The bigger the number, the
|
||||
* smaller the tiles
|
||||
*/
|
||||
obj_props[PROP_Y_TILES] =
|
||||
g_param_spec_uint ("y-tiles", NULL, NULL,
|
||||
1, G_MAXUINT,
|
||||
DEFAULT_N_TILES,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* ClutterDeformEffect:back-material:
|
||||
*
|
||||
* A material to be used when painting the back of the actor
|
||||
* to which this effect has been applied
|
||||
*
|
||||
* By default, no material will be used
|
||||
*/
|
||||
obj_props[PROP_BACK_MATERIAL] =
|
||||
g_param_spec_object ("back-material", NULL, NULL,
|
||||
COGL_TYPE_PIPELINE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
gobject_class->finalize = clutter_deform_effect_finalize;
|
||||
gobject_class->set_property = clutter_deform_effect_set_property;
|
||||
gobject_class->get_property = clutter_deform_effect_get_property;
|
||||
g_object_class_install_properties (gobject_class,
|
||||
PROP_LAST,
|
||||
obj_props);
|
||||
|
||||
meta_class->set_actor = clutter_deform_effect_set_actor;
|
||||
|
||||
offscreen_class->paint_target = clutter_deform_effect_paint_target;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_deform_effect_init (ClutterDeformEffect *self)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv =
|
||||
clutter_deform_effect_get_instance_private (self);
|
||||
|
||||
priv->x_tiles = priv->y_tiles = DEFAULT_N_TILES;
|
||||
priv->back_pipeline = NULL;
|
||||
|
||||
clutter_deform_effect_init_arrays (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_deform_effect_set_back_material:
|
||||
* @effect: a #ClutterDeformEffect
|
||||
* @material: (allow-none): a handle to a Cogl material
|
||||
*
|
||||
* Sets the material that should be used when drawing the back face
|
||||
* of the actor during a deformation
|
||||
*
|
||||
* The #ClutterDeformEffect will take a reference on the material's
|
||||
* handle
|
||||
*/
|
||||
void
|
||||
clutter_deform_effect_set_back_material (ClutterDeformEffect *effect,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect));
|
||||
g_return_if_fail (pipeline == NULL || COGL_IS_PIPELINE (pipeline));
|
||||
|
||||
priv = clutter_deform_effect_get_instance_private (effect);
|
||||
|
||||
clutter_deform_effect_free_back_pipeline (effect);
|
||||
|
||||
priv->back_pipeline = pipeline;
|
||||
if (priv->back_pipeline != NULL)
|
||||
g_object_ref (priv->back_pipeline);
|
||||
|
||||
clutter_deform_effect_invalidate (effect);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_deform_effect_get_back_material:
|
||||
* @effect: a #ClutterDeformEffect
|
||||
*
|
||||
* Retrieves the handle to the back face material used by @effect
|
||||
*
|
||||
* Return value: (transfer none): a handle for the material, or %NULL.
|
||||
* The returned material is owned by the #ClutterDeformEffect and it
|
||||
* should not be freed directly
|
||||
*/
|
||||
CoglPipeline*
|
||||
clutter_deform_effect_get_back_material (ClutterDeformEffect *effect)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect), NULL);
|
||||
|
||||
priv = clutter_deform_effect_get_instance_private (effect);
|
||||
return priv->back_pipeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_deform_effect_set_n_tiles:
|
||||
* @effect: a #ClutterDeformEffect
|
||||
* @x_tiles: number of horizontal tiles
|
||||
* @y_tiles: number of vertical tiles
|
||||
*
|
||||
* Sets the number of horizontal and vertical tiles to be used
|
||||
* when applying the effect
|
||||
*
|
||||
* More tiles allow a finer grained deformation at the expenses
|
||||
* of computation
|
||||
*/
|
||||
void
|
||||
clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect,
|
||||
guint x_tiles,
|
||||
guint y_tiles)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv;
|
||||
gboolean tiles_changed = FALSE;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect));
|
||||
g_return_if_fail (x_tiles > 0 && y_tiles > 0);
|
||||
|
||||
priv = clutter_deform_effect_get_instance_private (effect);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (effect));
|
||||
|
||||
if (priv->x_tiles != x_tiles)
|
||||
{
|
||||
priv->x_tiles = x_tiles;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_X_TILES]);
|
||||
|
||||
tiles_changed = TRUE;
|
||||
}
|
||||
|
||||
if (priv->y_tiles != y_tiles)
|
||||
{
|
||||
priv->y_tiles = y_tiles;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_Y_TILES]);
|
||||
|
||||
tiles_changed = TRUE;
|
||||
}
|
||||
|
||||
if (tiles_changed)
|
||||
{
|
||||
clutter_deform_effect_init_arrays (effect);
|
||||
clutter_deform_effect_invalidate (effect);
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (effect));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_deform_effect_get_n_tiles:
|
||||
* @effect: a #ClutterDeformEffect
|
||||
* @x_tiles: (out): return location for the number of horizontal tiles,
|
||||
* or %NULL
|
||||
* @y_tiles: (out): return location for the number of vertical tiles,
|
||||
* or %NULL
|
||||
*
|
||||
* Retrieves the number of horizontal and vertical tiles used to sub-divide
|
||||
* the actor's geometry during the effect
|
||||
*/
|
||||
void
|
||||
clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect,
|
||||
guint *x_tiles,
|
||||
guint *y_tiles)
|
||||
{
|
||||
ClutterDeformEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect));
|
||||
|
||||
priv = clutter_deform_effect_get_instance_private (effect);
|
||||
if (x_tiles != NULL)
|
||||
*x_tiles = priv->x_tiles;
|
||||
|
||||
if (y_tiles != NULL)
|
||||
*y_tiles = priv->y_tiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_deform_effect_invalidate:
|
||||
* @effect: a #ClutterDeformEffect
|
||||
*
|
||||
* Invalidates the `effect`'s vertices and, if it is associated
|
||||
* to an actor, it will queue a redraw
|
||||
*/
|
||||
void
|
||||
clutter_deform_effect_invalidate (ClutterDeformEffect *effect)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
ClutterDeformEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_DEFORM_EFFECT (effect));
|
||||
|
||||
priv = clutter_deform_effect_get_instance_private (effect);
|
||||
if (priv->is_dirty)
|
||||
return;
|
||||
|
||||
priv->is_dirty = TRUE;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
if (actor != NULL)
|
||||
clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
|
||||
}
|
82
mutter/clutter/clutter/clutter-deform-effect.h
Normal file
82
mutter/clutter/clutter/clutter-deform-effect.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
#include "clutter/clutter-offscreen-effect.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_DEFORM_EFFECT (clutter_deform_effect_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterDeformEffect,
|
||||
clutter_deform_effect,
|
||||
CLUTTER,
|
||||
DEFORM_EFFECT,
|
||||
ClutterOffscreenEffect)
|
||||
|
||||
/**
|
||||
* ClutterDeformEffectClass:
|
||||
* @deform_vertex: virtual function; sub-classes should override this
|
||||
* function to compute the deformation of each vertex
|
||||
*
|
||||
* The #ClutterDeformEffectClass structure contains
|
||||
* only private data
|
||||
*/
|
||||
struct _ClutterDeformEffectClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterOffscreenEffectClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (* deform_vertex) (ClutterDeformEffect *effect,
|
||||
gfloat width,
|
||||
gfloat height,
|
||||
CoglTextureVertex *vertex);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_deform_effect_set_back_material (ClutterDeformEffect *effect,
|
||||
CoglPipeline *material);
|
||||
CLUTTER_EXPORT
|
||||
CoglPipeline* clutter_deform_effect_get_back_material (ClutterDeformEffect *effect);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_deform_effect_set_n_tiles (ClutterDeformEffect *effect,
|
||||
guint x_tiles,
|
||||
guint y_tiles);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_deform_effect_get_n_tiles (ClutterDeformEffect *effect,
|
||||
guint *x_tiles,
|
||||
guint *y_tiles);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_deform_effect_invalidate (ClutterDeformEffect *effect);
|
||||
|
||||
G_END_DECLS
|
306
mutter/clutter/clutter/clutter-desaturate-effect.c
Normal file
306
mutter/clutter/clutter/clutter-desaturate-effect.c
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterDesaturateEffect:
|
||||
*
|
||||
* A desaturation effect
|
||||
*
|
||||
* #ClutterDesaturateEffect is a sub-class of #ClutterEffect that
|
||||
* desaturates the color of an actor and its contents. The strength
|
||||
* of the desaturation effect is controllable and animatable through
|
||||
* the #ClutterDesaturateEffect:factor property.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter/clutter-desaturate-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
|
||||
typedef struct _ClutterDesaturateEffectPrivate
|
||||
{
|
||||
/* the desaturation factor, also known as "strength" */
|
||||
gdouble factor;
|
||||
|
||||
gint factor_uniform;
|
||||
|
||||
gint tex_width;
|
||||
gint tex_height;
|
||||
|
||||
CoglPipeline *pipeline;
|
||||
} ClutterDesaturateEffectPrivate;
|
||||
|
||||
|
||||
/* the magic gray vec3 has been taken from the NTSC conversion weights
|
||||
* as defined by:
|
||||
*
|
||||
* "OpenGL Superbible, 4th edition"
|
||||
* -- Richard S. Wright Jr, Benjamin Lipchak, Nicholas Haemel
|
||||
* Addison-Wesley
|
||||
*/
|
||||
static const gchar *desaturate_glsl_declarations =
|
||||
"uniform float factor;\n"
|
||||
"\n"
|
||||
"vec3 desaturate (const vec3 color, const float desaturation)\n"
|
||||
"{\n"
|
||||
" const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n"
|
||||
" vec3 gray = vec3 (dot (gray_conv, color));\n"
|
||||
" return vec3 (mix (color.rgb, gray, desaturation));\n"
|
||||
"}\n";
|
||||
|
||||
static const gchar *desaturate_glsl_source =
|
||||
" cogl_color_out.rgb = desaturate (cogl_color_out.rgb, factor);\n";
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_FACTOR,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (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);
|
||||
ClutterDesaturateEffectPrivate *priv =
|
||||
clutter_desaturate_effect_get_instance_private (desaturate_effect);
|
||||
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
|
||||
|
||||
return g_object_ref (priv->pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (gobject);
|
||||
ClutterDesaturateEffectPrivate *priv =
|
||||
clutter_desaturate_effect_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->pipeline);
|
||||
|
||||
G_OBJECT_CLASS (clutter_desaturate_effect_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterDesaturateEffect *effect = CLUTTER_DESATURATE_EFFECT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FACTOR:
|
||||
clutter_desaturate_effect_set_factor (effect,
|
||||
g_value_get_double (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterDesaturateEffect *effect = CLUTTER_DESATURATE_EFFECT (gobject);
|
||||
ClutterDesaturateEffectPrivate *priv =
|
||||
clutter_desaturate_effect_get_instance_private (effect);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FACTOR:
|
||||
g_value_set_double (value, priv->factor);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_factor_uniform (ClutterDesaturateEffect *self)
|
||||
{
|
||||
ClutterDesaturateEffectPrivate *priv =
|
||||
clutter_desaturate_effect_get_instance_private (self);
|
||||
|
||||
if (priv->factor_uniform > -1)
|
||||
cogl_pipeline_set_uniform_1f (priv->pipeline,
|
||||
priv->factor_uniform,
|
||||
priv->factor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterOffscreenEffectClass *offscreen_class;
|
||||
|
||||
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
|
||||
offscreen_class->create_pipeline = clutter_desaturate_effect_create_pipeline;
|
||||
|
||||
/**
|
||||
* ClutterDesaturateEffect:factor:
|
||||
*
|
||||
* The desaturation factor, between 0.0 (no desaturation) and 1.0 (full
|
||||
* desaturation).
|
||||
*/
|
||||
obj_props[PROP_FACTOR] =
|
||||
g_param_spec_double ("factor", NULL, NULL,
|
||||
0.0, 1.0,
|
||||
1.0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
gobject_class->dispose = clutter_desaturate_effect_dispose;
|
||||
gobject_class->set_property = clutter_desaturate_effect_set_property;
|
||||
gobject_class->get_property = clutter_desaturate_effect_get_property;
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_desaturate_effect_init (ClutterDesaturateEffect *self)
|
||||
{
|
||||
ClutterDesaturateEffectClass *klass = CLUTTER_DESATURATE_EFFECT_GET_CLASS (self);
|
||||
ClutterDesaturateEffectPrivate *priv =
|
||||
clutter_desaturate_effect_get_instance_private (self);
|
||||
|
||||
if (G_UNLIKELY (klass->base_pipeline == NULL))
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglSnippet *snippet;
|
||||
|
||||
klass->base_pipeline = cogl_pipeline_new (ctx);
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
|
||||
desaturate_glsl_declarations,
|
||||
desaturate_glsl_source);
|
||||
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
|
||||
g_object_unref (snippet);
|
||||
|
||||
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
|
||||
}
|
||||
|
||||
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
||||
|
||||
priv->factor_uniform =
|
||||
cogl_pipeline_get_uniform_location (priv->pipeline, "factor");
|
||||
|
||||
priv->factor = 1.0;
|
||||
|
||||
update_factor_uniform (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_desaturate_effect_new:
|
||||
* @factor: the desaturation factor, between 0.0 and 1.0
|
||||
*
|
||||
* Creates a new #ClutterDesaturateEffect to be used with
|
||||
* [method@Clutter.Actor.add_effect]
|
||||
*
|
||||
* Return value: the newly created #ClutterDesaturateEffect or %NULL
|
||||
*/
|
||||
ClutterEffect *
|
||||
clutter_desaturate_effect_new (gdouble factor)
|
||||
{
|
||||
g_return_val_if_fail (factor >= 0.0 && factor <= 1.0, NULL);
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_DESATURATE_EFFECT,
|
||||
"factor", factor,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_desaturate_effect_set_factor:
|
||||
* @effect: a #ClutterDesaturateEffect
|
||||
* @factor: the desaturation factor, between 0.0 and 1.0
|
||||
*
|
||||
* Sets the desaturation factor for @effect, with 0.0 being "do not desaturate"
|
||||
* and 1.0 being "fully desaturate"
|
||||
*/
|
||||
void
|
||||
clutter_desaturate_effect_set_factor (ClutterDesaturateEffect *effect,
|
||||
double factor)
|
||||
{
|
||||
ClutterDesaturateEffectPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_DESATURATE_EFFECT (effect));
|
||||
g_return_if_fail (factor >= 0.0 && factor <= 1.0);
|
||||
|
||||
priv = clutter_desaturate_effect_get_instance_private (effect);
|
||||
if (fabs (priv->factor - factor) >= 0.00001)
|
||||
{
|
||||
priv->factor = factor;
|
||||
update_factor_uniform (effect);
|
||||
|
||||
clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (effect), obj_props[PROP_FACTOR]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_desaturate_effect_get_factor:
|
||||
* @effect: a #ClutterDesaturateEffect
|
||||
*
|
||||
* Retrieves the desaturation factor of @effect
|
||||
*
|
||||
* Return value: the desaturation factor
|
||||
*/
|
||||
gdouble
|
||||
clutter_desaturate_effect_get_factor (ClutterDesaturateEffect *effect)
|
||||
{
|
||||
ClutterDesaturateEffectPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_DESATURATE_EFFECT (effect), 0.0);
|
||||
|
||||
priv = clutter_desaturate_effect_get_instance_private (effect);
|
||||
return priv->factor;
|
||||
}
|
60
mutter/clutter/clutter/clutter-desaturate-effect.h
Normal file
60
mutter/clutter/clutter/clutter-desaturate-effect.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-effect.h"
|
||||
#include "clutter/clutter-offscreen-effect.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_DESATURATE_EFFECT (clutter_desaturate_effect_get_type ())
|
||||
|
||||
struct _ClutterDesaturateEffectClass
|
||||
{
|
||||
ClutterOffscreenEffectClass parent_class;
|
||||
|
||||
CoglPipeline *base_pipeline;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterDesaturateEffect,
|
||||
clutter_desaturate_effect,
|
||||
CLUTTER, DESATURATE_EFFECT,
|
||||
ClutterOffscreenEffect)
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterEffect *clutter_desaturate_effect_new (gdouble factor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_desaturate_effect_set_factor (ClutterDesaturateEffect *effect,
|
||||
gdouble factor);
|
||||
CLUTTER_EXPORT
|
||||
gdouble clutter_desaturate_effect_get_factor (ClutterDesaturateEffect *effect);
|
||||
|
||||
G_END_DECLS
|
555
mutter/clutter/clutter/clutter-easing.c
Normal file
555
mutter/clutter/clutter/clutter-easing.c
Normal file
@ -0,0 +1,555 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-easing.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
double
|
||||
clutter_linear (double t,
|
||||
double d)
|
||||
{
|
||||
return t / d;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_quad (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return p * p;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_quad (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return -1.0 * p * (p - 2);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_quad (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
return 0.5 * p * p;
|
||||
|
||||
p -= 1;
|
||||
|
||||
return -0.5 * (p * (p - 2) - 1);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_cubic (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return p * p * p;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_cubic (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d - 1;
|
||||
|
||||
return p * p * p + 1;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_cubic (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
return 0.5 * p * p * p;
|
||||
|
||||
p -= 2;
|
||||
|
||||
return 0.5 * (p * p * p + 2);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_quart (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return p * p * p * p;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_quart (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d - 1;
|
||||
|
||||
return -1.0 * (p * p * p * p - 1);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_quart (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
return 0.5 * p * p * p * p;
|
||||
|
||||
p -= 2;
|
||||
|
||||
return -0.5 * (p * p * p * p - 2);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_quint (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return p * p * p * p * p;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_quint (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d - 1;
|
||||
|
||||
return p * p * p * p * p + 1;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_quint (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
return 0.5 * p * p * p * p * p;
|
||||
|
||||
p -= 2;
|
||||
|
||||
return 0.5 * (p * p * p * p * p + 2);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_sine (double t,
|
||||
double d)
|
||||
{
|
||||
return -1.0 * cos (t / d * G_PI_2) + 1.0;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_sine (double t,
|
||||
double d)
|
||||
{
|
||||
return sin (t / d * G_PI_2);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_sine (double t,
|
||||
double d)
|
||||
{
|
||||
return -0.5 * (cos (G_PI * t / d) - 1);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_expo (double t,
|
||||
double d)
|
||||
{
|
||||
return (t == 0) ? 0.0 : pow (2, 10 * (t / d - 1));
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_expo (double t,
|
||||
double d)
|
||||
{
|
||||
return (t == d) ? 1.0 : -pow (2, -10 * t / d) + 1;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_expo (double t,
|
||||
double d)
|
||||
{
|
||||
double p;
|
||||
|
||||
if (t == 0)
|
||||
return 0.0;
|
||||
|
||||
if (t == d)
|
||||
return 1.0;
|
||||
|
||||
p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
return 0.5 * pow (2, 10 * (p - 1));
|
||||
|
||||
p -= 1;
|
||||
|
||||
return 0.5 * (-pow (2, -10 * p) + 2);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_circ (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return -1.0 * (sqrt (1 - p * p) - 1);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_circ (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d - 1;
|
||||
|
||||
return sqrt (1 - p * p);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_circ (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
return -0.5 * (sqrt (1 - p * p) - 1);
|
||||
|
||||
p -= 2;
|
||||
|
||||
return 0.5 * (sqrt (1 - p * p) + 1);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_elastic (double t,
|
||||
double d)
|
||||
{
|
||||
double p = d * .3;
|
||||
double s = p / 4;
|
||||
double q = t / d;
|
||||
|
||||
if (q == 1)
|
||||
return 1.0;
|
||||
|
||||
q -= 1;
|
||||
|
||||
return -(pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p));
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_elastic (double t,
|
||||
double d)
|
||||
{
|
||||
double p = d * .3;
|
||||
double s = p / 4;
|
||||
double q = t / d;
|
||||
|
||||
if (q == 1)
|
||||
return 1.0;
|
||||
|
||||
return pow (2, -10 * q) * sin ((q * d - s) * (2 * G_PI) / p) + 1.0;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_elastic (double t,
|
||||
double d)
|
||||
{
|
||||
double p = d * (.3 * 1.5);
|
||||
double s = p / 4;
|
||||
double q = t / (d / 2);
|
||||
|
||||
if (q == 2)
|
||||
return 1.0;
|
||||
|
||||
if (q < 1)
|
||||
{
|
||||
q -= 1;
|
||||
|
||||
return -.5 * (pow (2, 10 * q) * sin ((q * d - s) * (2 * G_PI) / p));
|
||||
}
|
||||
else
|
||||
{
|
||||
q -= 1;
|
||||
|
||||
return pow (2, -10 * q)
|
||||
* sin ((q * d - s) * (2 * G_PI) / p)
|
||||
* .5 + 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_back (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
return p * p * ((1.70158 + 1) * p - 1.70158);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_back (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d - 1;
|
||||
|
||||
return p * p * ((1.70158 + 1) * p + 1.70158) + 1;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_back (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / (d / 2);
|
||||
double s = 1.70158 * 1.525;
|
||||
|
||||
if (p < 1)
|
||||
return 0.5 * (p * p * ((s + 1) * p - s));
|
||||
|
||||
p -= 2;
|
||||
|
||||
return 0.5 * (p * p * ((s + 1) * p + s) + 2);
|
||||
}
|
||||
|
||||
static inline double
|
||||
ease_out_bounce_internal (double t,
|
||||
double d)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
if (p < (1 / 2.75))
|
||||
{
|
||||
return 7.5625 * p * p;
|
||||
}
|
||||
else if (p < (2 / 2.75))
|
||||
{
|
||||
p -= (1.5 / 2.75);
|
||||
|
||||
return 7.5625 * p * p + .75;
|
||||
}
|
||||
else if (p < (2.5 / 2.75))
|
||||
{
|
||||
p -= (2.25 / 2.75);
|
||||
|
||||
return 7.5625 * p * p + .9375;
|
||||
}
|
||||
else
|
||||
{
|
||||
p -= (2.625 / 2.75);
|
||||
|
||||
return 7.5625 * p * p + .984375;
|
||||
}
|
||||
}
|
||||
|
||||
static inline double
|
||||
ease_in_bounce_internal (double t,
|
||||
double d)
|
||||
{
|
||||
return 1.0 - ease_out_bounce_internal (d - t, d);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_bounce (double t,
|
||||
double d)
|
||||
{
|
||||
return ease_in_bounce_internal (t, d);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_out_bounce (double t,
|
||||
double d)
|
||||
{
|
||||
return ease_out_bounce_internal (t, d);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_in_out_bounce (double t,
|
||||
double d)
|
||||
{
|
||||
if (t < d / 2)
|
||||
return ease_in_bounce_internal (t * 2, d) * 0.5;
|
||||
else
|
||||
return ease_out_bounce_internal (t * 2 - d, d) * 0.5 + 1.0 * 0.5;
|
||||
}
|
||||
|
||||
static inline double
|
||||
ease_steps_end (double p,
|
||||
int n_steps)
|
||||
{
|
||||
return floor (p * (double) n_steps) / (double) n_steps;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_steps_start (double t,
|
||||
double d,
|
||||
int n_steps)
|
||||
{
|
||||
return 1.0 - ease_steps_end (1.0 - (t / d), n_steps);
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_steps_end (double t,
|
||||
double d,
|
||||
int n_steps)
|
||||
{
|
||||
return ease_steps_end ((t / d), n_steps);
|
||||
}
|
||||
|
||||
static inline double
|
||||
x_for_t (double t,
|
||||
double x_1,
|
||||
double x_2)
|
||||
{
|
||||
double omt = 1.0 - t;
|
||||
|
||||
return 3.0 * omt * omt * t * x_1
|
||||
+ 3.0 * omt * t * t * x_2
|
||||
+ t * t * t;
|
||||
}
|
||||
|
||||
static inline double
|
||||
y_for_t (double t,
|
||||
double y_1,
|
||||
double y_2)
|
||||
{
|
||||
double omt = 1.0 - t;
|
||||
|
||||
return 3.0 * omt * omt * t * y_1
|
||||
+ 3.0 * omt * t * t * y_2
|
||||
+ t * t * t;
|
||||
}
|
||||
|
||||
static inline double
|
||||
t_for_x (double x,
|
||||
double x_1,
|
||||
double x_2)
|
||||
{
|
||||
double min_t = 0, max_t = 1;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 30; ++i)
|
||||
{
|
||||
double guess_t = (min_t + max_t) / 2.0;
|
||||
double guess_x = x_for_t (guess_t, x_1, x_2);
|
||||
|
||||
if (x < guess_x)
|
||||
max_t = guess_t;
|
||||
else
|
||||
min_t = guess_t;
|
||||
}
|
||||
|
||||
return (min_t + max_t) / 2.0;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_ease_cubic_bezier (double t,
|
||||
double d,
|
||||
double x_1,
|
||||
double y_1,
|
||||
double x_2,
|
||||
double y_2)
|
||||
{
|
||||
double p = t / d;
|
||||
|
||||
if (p == 0.0)
|
||||
return 0.0;
|
||||
|
||||
if (p == 1.0)
|
||||
return 1.0;
|
||||
|
||||
return y_for_t (t_for_x (p, x_1, x_2), y_1, y_2);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* _clutter_animation_modes:
|
||||
*
|
||||
* A mapping of animation modes and easing functions.
|
||||
*/
|
||||
static const struct {
|
||||
ClutterAnimationMode mode;
|
||||
ClutterEasingFunc func;
|
||||
const char *name;
|
||||
} _clutter_animation_modes[] = {
|
||||
{ CLUTTER_CUSTOM_MODE, NULL, "custom" },
|
||||
|
||||
{ CLUTTER_LINEAR, clutter_linear, "linear" },
|
||||
{ CLUTTER_EASE_IN_QUAD, clutter_ease_in_quad, "easeInQuad" },
|
||||
{ CLUTTER_EASE_OUT_QUAD, clutter_ease_out_quad, "easeOutQuad" },
|
||||
{ CLUTTER_EASE_IN_OUT_QUAD, clutter_ease_in_out_quad, "easeInOutQuad" },
|
||||
{ CLUTTER_EASE_IN_CUBIC, clutter_ease_in_cubic, "easeInCubic" },
|
||||
{ CLUTTER_EASE_OUT_CUBIC, clutter_ease_out_cubic, "easeOutCubic" },
|
||||
{ CLUTTER_EASE_IN_OUT_CUBIC, clutter_ease_in_out_cubic, "easeInOutCubic" },
|
||||
{ CLUTTER_EASE_IN_QUART, clutter_ease_in_quart, "easeInQuart" },
|
||||
{ CLUTTER_EASE_OUT_QUART, clutter_ease_out_quart, "easeOutQuart" },
|
||||
{ CLUTTER_EASE_IN_OUT_QUART, clutter_ease_in_out_quart, "easeInOutQuart" },
|
||||
{ CLUTTER_EASE_IN_QUINT, clutter_ease_in_quint, "easeInQuint" },
|
||||
{ CLUTTER_EASE_OUT_QUINT, clutter_ease_out_quint, "easeOutQuint" },
|
||||
{ CLUTTER_EASE_IN_OUT_QUINT, clutter_ease_in_out_quint, "easeInOutQuint" },
|
||||
{ CLUTTER_EASE_IN_SINE, clutter_ease_in_sine, "easeInSine" },
|
||||
{ CLUTTER_EASE_OUT_SINE, clutter_ease_out_sine, "easeOutSine" },
|
||||
{ CLUTTER_EASE_IN_OUT_SINE, clutter_ease_in_out_sine, "easeInOutSine" },
|
||||
{ CLUTTER_EASE_IN_EXPO, clutter_ease_in_expo, "easeInExpo" },
|
||||
{ CLUTTER_EASE_OUT_EXPO, clutter_ease_out_expo, "easeOutExpo" },
|
||||
{ CLUTTER_EASE_IN_OUT_EXPO, clutter_ease_in_out_expo, "easeInOutExpo" },
|
||||
{ CLUTTER_EASE_IN_CIRC, clutter_ease_in_circ, "easeInCirc" },
|
||||
{ CLUTTER_EASE_OUT_CIRC, clutter_ease_out_circ, "easeOutCirc" },
|
||||
{ CLUTTER_EASE_IN_OUT_CIRC, clutter_ease_in_out_circ, "easeInOutCirc" },
|
||||
{ CLUTTER_EASE_IN_ELASTIC, clutter_ease_in_elastic, "easeInElastic" },
|
||||
{ CLUTTER_EASE_OUT_ELASTIC, clutter_ease_out_elastic, "easeOutElastic" },
|
||||
{ CLUTTER_EASE_IN_OUT_ELASTIC, clutter_ease_in_out_elastic, "easeInOutElastic" },
|
||||
{ CLUTTER_EASE_IN_BACK, clutter_ease_in_back, "easeInBack" },
|
||||
{ CLUTTER_EASE_OUT_BACK, clutter_ease_out_back, "easeOutBack" },
|
||||
{ CLUTTER_EASE_IN_OUT_BACK, clutter_ease_in_out_back, "easeInOutBack" },
|
||||
{ CLUTTER_EASE_IN_BOUNCE, clutter_ease_in_bounce, "easeInBounce" },
|
||||
{ CLUTTER_EASE_OUT_BOUNCE, clutter_ease_out_bounce, "easeOutBounce" },
|
||||
{ CLUTTER_EASE_IN_OUT_BOUNCE, clutter_ease_in_out_bounce, "easeInOutBounce" },
|
||||
|
||||
/* the parametrized functions need a cast */
|
||||
{ CLUTTER_STEPS, (ClutterEasingFunc) clutter_ease_steps_end, "steps" },
|
||||
{ CLUTTER_STEP_START, (ClutterEasingFunc) clutter_ease_steps_start, "stepStart" },
|
||||
{ CLUTTER_STEP_END, (ClutterEasingFunc) clutter_ease_steps_end, "stepEnd" },
|
||||
|
||||
{ CLUTTER_CUBIC_BEZIER, (ClutterEasingFunc) clutter_ease_cubic_bezier, "cubicBezier" },
|
||||
{ CLUTTER_EASE, (ClutterEasingFunc) clutter_ease_cubic_bezier, "ease" },
|
||||
{ CLUTTER_EASE_IN, (ClutterEasingFunc) clutter_ease_cubic_bezier, "easeIn" },
|
||||
{ CLUTTER_EASE_OUT, (ClutterEasingFunc) clutter_ease_cubic_bezier, "easeOut" },
|
||||
{ CLUTTER_EASE_IN_OUT, (ClutterEasingFunc) clutter_ease_cubic_bezier, "easeInOut" },
|
||||
|
||||
{ CLUTTER_ANIMATION_LAST, NULL, "sentinel" },
|
||||
};
|
||||
|
||||
ClutterEasingFunc
|
||||
clutter_get_easing_func_for_mode (ClutterAnimationMode mode)
|
||||
{
|
||||
g_assert (_clutter_animation_modes[mode].mode == mode);
|
||||
g_assert (_clutter_animation_modes[mode].func != NULL);
|
||||
|
||||
return _clutter_animation_modes[mode].func;
|
||||
}
|
||||
|
||||
const char *
|
||||
clutter_get_easing_name_for_mode (ClutterAnimationMode mode)
|
||||
{
|
||||
g_assert (_clutter_animation_modes[mode].mode == mode);
|
||||
g_assert (_clutter_animation_modes[mode].func != NULL);
|
||||
|
||||
return _clutter_animation_modes[mode].name;
|
||||
}
|
||||
|
||||
double
|
||||
clutter_easing_for_mode (ClutterAnimationMode mode,
|
||||
double t,
|
||||
double d)
|
||||
{
|
||||
g_assert (_clutter_animation_modes[mode].mode == mode);
|
||||
g_assert (_clutter_animation_modes[mode].func != NULL);
|
||||
|
||||
return _clutter_animation_modes[mode].func (t, d);
|
||||
}
|
139
mutter/clutter/clutter/clutter-easing.h
Normal file
139
mutter/clutter/clutter/clutter-easing.h
Normal file
@ -0,0 +1,139 @@
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*< private >
|
||||
* ClutterEasingFunc:
|
||||
* @t: elapsed time
|
||||
* @d: total duration
|
||||
*
|
||||
* Internal type for the easing functions used by Clutter.
|
||||
*
|
||||
* Return value: the interpolated value, between -1.0 and 2.0
|
||||
*/
|
||||
typedef double (* ClutterEasingFunc) (double t, double d);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
ClutterEasingFunc clutter_get_easing_func_for_mode (ClutterAnimationMode mode);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
const char * clutter_get_easing_name_for_mode (ClutterAnimationMode mode);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_easing_for_mode (ClutterAnimationMode mode,
|
||||
double t,
|
||||
double d);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_linear (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_quad (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_quad (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_quad (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_cubic (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_cubic (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_cubic (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_quart (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_quart (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_quart (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_quint (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_quint (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_quint (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_sine (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_sine (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_sine (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_expo (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_expo (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_expo (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_circ (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_circ (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_circ (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_elastic (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_elastic (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_elastic (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_back (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_back (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_back (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_bounce (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_out_bounce (double t,
|
||||
double d);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_in_out_bounce (double t,
|
||||
double d);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_steps_start (double t,
|
||||
double d,
|
||||
int steps);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_steps_end (double t,
|
||||
double d,
|
||||
int steps);
|
||||
G_GNUC_INTERNAL
|
||||
double clutter_ease_cubic_bezier (double t,
|
||||
double d,
|
||||
double x_1,
|
||||
double y_1,
|
||||
double x_2,
|
||||
double y_2);
|
||||
|
||||
G_END_DECLS
|
17
mutter/clutter/clutter/clutter-effect-private.h
Normal file
17
mutter/clutter/clutter/clutter-effect-private.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "clutter/clutter-effect.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
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,
|
||||
ClutterPickContext *pick_context);
|
||||
|
||||
G_END_DECLS
|
397
mutter/clutter/clutter/clutter-effect.c
Normal file
397
mutter/clutter/clutter/clutter-effect.c
Normal file
@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* ClutterEffect:
|
||||
*
|
||||
* Base class for actor effects
|
||||
*
|
||||
* The #ClutterEffect class provides a default type and API for creating
|
||||
* effects for generic actors.
|
||||
*
|
||||
* Effects are a #ClutterActorMeta sub-class that modify the way an actor
|
||||
* is painted in a way that is not part of the actor's implementation.
|
||||
*
|
||||
* Effects should be the preferred way to affect the paint sequence of an
|
||||
* actor without sub-classing the actor itself and overriding the
|
||||
* [vfunc@Clutter.Actor.paint] virtual function.
|
||||
*
|
||||
* ## Implementing a ClutterEffect
|
||||
*
|
||||
* Creating a sub-class of #ClutterEffect requires overriding the
|
||||
* [vfunc@Clutter.Effect.paint] method. The implementation of the function should look
|
||||
* something like this:
|
||||
*
|
||||
* ```c
|
||||
* void effect_paint (ClutterEffect *effect, ClutterEffectPaintFlags flags)
|
||||
* {
|
||||
* // Set up initialisation of the paint such as binding a
|
||||
* // CoglOffscreen or other operations
|
||||
*
|
||||
* // Chain to the next item in the paint sequence. This will either call
|
||||
* // ‘paint’ on the next effect or just paint the actor if this is
|
||||
* // the last effect.
|
||||
* ClutterActor *actor =
|
||||
* clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
*
|
||||
* clutter_actor_continue_paint (actor);
|
||||
*
|
||||
* // perform any cleanup of state, such as popping the CoglOffscreen
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The effect can optionally avoid calling clutter_actor_continue_paint() to skip any
|
||||
* further stages of the paint sequence. This is useful for example if the effect
|
||||
* contains a cached image of the actor. In that case it can optimise painting by
|
||||
* avoiding the actor paint and instead painting the cached image.
|
||||
*
|
||||
* The %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag is useful in this case. Clutter will set
|
||||
* this flag when a redraw has been queued on the actor since it was last painted. The
|
||||
* effect can use this information to decide if the cached image is still valid.
|
||||
*
|
||||
* ## A simple ClutterEffect implementation
|
||||
*
|
||||
* The example below creates two rectangles: one will be painted "behind" the actor,
|
||||
* while another will be painted "on top" of the actor.
|
||||
*
|
||||
* The #ClutterActorMetaClass.set_actor() implementation will create the two materials
|
||||
* used for the two different rectangles; the #ClutterEffectClass.paint() implementation
|
||||
* will paint the first material using cogl_rectangle(), before continuing and then it
|
||||
* will paint paint the second material after.
|
||||
*
|
||||
* ```c
|
||||
* typedef struct {
|
||||
* ClutterEffect parent_instance;
|
||||
*
|
||||
* CoglPipeline *rect_1;
|
||||
* CoglPipeline *rect_2;
|
||||
* } MyEffect;
|
||||
*
|
||||
* typedef struct _ClutterEffectClass MyEffectClass;
|
||||
*
|
||||
* G_DEFINE_TYPE (MyEffect, my_effect, CLUTTER_TYPE_EFFECT);
|
||||
*
|
||||
* static void
|
||||
* my_effect_set_actor (ClutterActorMeta *meta,
|
||||
* ClutterActor *actor)
|
||||
* {
|
||||
* MyEffect *self = MY_EFFECT (meta);
|
||||
* CoglColor color;
|
||||
*
|
||||
* // Clear the previous state //
|
||||
* if (self->rect_1)
|
||||
* {
|
||||
* g_object_unref (self->rect_1);
|
||||
* self->rect_1 = NULL;
|
||||
* }
|
||||
*
|
||||
* if (self->rect_2)
|
||||
* {
|
||||
* g_object_unref (self->rect_2);
|
||||
* self->rect_2 = NULL;
|
||||
* }
|
||||
*
|
||||
* // Maintain a pointer to the actor
|
||||
* self->actor = actor;
|
||||
*
|
||||
* // If we've been detached by the actor then we should just bail out here
|
||||
* if (self->actor == NULL)
|
||||
* return;
|
||||
*
|
||||
* // Create a red material
|
||||
* self->rect_1 = cogl_pipeline_new ();
|
||||
* cogl_color_init_from_4f (&color, 1.0, 1.0, 1.0, 1.0);
|
||||
* cogl_pipeline_set_color (self->rect_1, &color);
|
||||
*
|
||||
* // Create a green material
|
||||
* self->rect_2 = cogl_pipeline_new ();
|
||||
* cogl_color_init_from_4f (&color, 0.0, 1.0, 0.0, 1.0);
|
||||
* cogl_pipeline_set_color (self->rect_2, &color);
|
||||
* }
|
||||
*
|
||||
* static gboolean
|
||||
* my_effect_paint (ClutterEffect *effect)
|
||||
* {
|
||||
* MyEffect *self = MY_EFFECT (effect);
|
||||
* gfloat width, height;
|
||||
*
|
||||
* clutter_actor_get_size (self->actor, &width, &height);
|
||||
*
|
||||
* // Paint the first rectangle in the upper left quadrant
|
||||
* cogl_set_source (self->rect_1);
|
||||
* cogl_rectangle (0, 0, width / 2, height / 2);
|
||||
*
|
||||
* // Continue to the rest of the paint sequence
|
||||
* clutter_actor_continue_paint (self->actor);
|
||||
*
|
||||
* // Paint the second rectangle in the lower right quadrant
|
||||
* cogl_set_source (self->rect_2);
|
||||
* cogl_rectangle (width / 2, height / 2, width, height);
|
||||
* }
|
||||
*
|
||||
* static void
|
||||
* my_effect_class_init (MyEffectClass *klass)
|
||||
* {
|
||||
* ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
*
|
||||
* meta_class->set_actor = my_effect_set_actor;
|
||||
*
|
||||
* klass->paint = my_effect_paint;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "clutter/clutter-effect.h"
|
||||
|
||||
#include "clutter/clutter-actor-meta-private.h"
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-effect-private.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
#include "clutter/clutter-marshal.h"
|
||||
#include "clutter/clutter-paint-node-private.h"
|
||||
#include "clutter/clutter-paint-nodes.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterEffect,
|
||||
clutter_effect,
|
||||
CLUTTER_TYPE_ACTOR_META);
|
||||
|
||||
static gboolean
|
||||
clutter_effect_real_pre_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_real_post_paint (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_real_pick (ClutterEffect *effect,
|
||||
ClutterPickContext *pick_context)
|
||||
{
|
||||
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (actor_meta);
|
||||
clutter_actor_continue_pick (actor, pick_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_set_enabled (ClutterActorMeta *meta,
|
||||
gboolean is_enabled)
|
||||
{
|
||||
ClutterActorMetaClass *parent_class =
|
||||
CLUTTER_ACTOR_META_CLASS (clutter_effect_parent_class);
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = clutter_actor_meta_get_actor (meta);
|
||||
if (actor)
|
||||
clutter_actor_queue_redraw (actor);
|
||||
|
||||
parent_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_class_init (ClutterEffectClass *klass)
|
||||
{
|
||||
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass);
|
||||
|
||||
actor_meta_class->set_enabled = clutter_effect_set_enabled;
|
||||
|
||||
klass->pre_paint = clutter_effect_real_pre_paint;
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_effect_init (ClutterEffect *self)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_effect_pick (ClutterEffect *effect,
|
||||
ClutterPickContext *pick_context)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, pick_context);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_effect_modify_paint_volume (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
||||
g_return_val_if_fail (volume != NULL, FALSE);
|
||||
|
||||
return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume (effect,
|
||||
volume);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
||||
|
||||
return CLUTTER_EFFECT_GET_CLASS (effect)->modify_paint_volume != clutter_effect_real_modify_paint_volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_effect_queue_repaint:
|
||||
* @effect: A #ClutterEffect which needs redrawing
|
||||
*
|
||||
* Queues a repaint of the effect. The effect can detect when the ‘paint’
|
||||
* method is called as a result of this function because it will not
|
||||
* have the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag set. In that case the
|
||||
* effect is free to assume that the actor has not changed its
|
||||
* appearance since the last time it was painted so it doesn't need to
|
||||
* call clutter_actor_continue_paint() if it can draw a cached
|
||||
* image. This is mostly intended for effects that are using a
|
||||
* %CoglOffscreen to redirect the actor (such as
|
||||
* %ClutterOffscreenEffect). In that case the effect can save a bit of
|
||||
* rendering time by painting the cached texture without causing the
|
||||
* entire actor to be painted.
|
||||
*
|
||||
* This function can be used by effects that have their own animatable
|
||||
* parameters. For example, an effect which adds a varying degree of a
|
||||
* red tint to an actor by redirecting it through a CoglOffscreen
|
||||
* might have a property to specify the level of tint. When this value
|
||||
* changes, the underlying actor doesn't need to be redrawn so the
|
||||
* effect can call clutter_effect_queue_repaint() to make sure the
|
||||
* effect is repainted.
|
||||
*
|
||||
* Note however that modifying the position of the parent of an actor
|
||||
* may change the appearance of the actor because its transformation
|
||||
* matrix would change. In this case a redraw wouldn't be queued on
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* anything queues a redraw on the actor without specifying an effect
|
||||
* or with an effect that is lower in the chain of effects than this
|
||||
* one then that will override this call. In that case this effect
|
||||
* will instead be called with the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY
|
||||
* flag set.
|
||||
*/
|
||||
void
|
||||
clutter_effect_queue_repaint (ClutterEffect *effect)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
|
||||
|
||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
|
||||
|
||||
/* If the effect has no actor then nothing needs to be done */
|
||||
if (actor != NULL)
|
||||
_clutter_actor_queue_redraw_full (actor,
|
||||
NULL, /* clip volume */
|
||||
effect /* effect */);
|
||||
}
|
115
mutter/clutter/clutter/clutter-effect.h
Normal file
115
mutter/clutter/clutter/clutter-effect.h
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corporation.
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-actor-meta.h"
|
||||
#include "clutter/clutter-paint-context.h"
|
||||
#include "clutter/clutter-pick-context.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_EFFECT (clutter_effect_get_type ())
|
||||
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterEffect,
|
||||
clutter_effect,
|
||||
CLUTTER,
|
||||
EFFECT,
|
||||
ClutterActorMeta)
|
||||
|
||||
/**
|
||||
* ClutterEffectClass:
|
||||
* @pre_paint: virtual function
|
||||
* @post_paint: virtual function
|
||||
* @modify_paint_volume: virtual function
|
||||
* @paint: virtual function
|
||||
* @pick: virtual function
|
||||
*
|
||||
* The #ClutterEffectClass structure contains only private data
|
||||
*/
|
||||
struct _ClutterEffectClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorMetaClass parent_class;
|
||||
|
||||
/*< 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,
|
||||
ClutterPickContext *pick_context);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_effect_queue_repaint (ClutterEffect *effect);
|
||||
|
||||
/*
|
||||
* ClutterActor API
|
||||
*/
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_effect (ClutterActor *self,
|
||||
ClutterEffect *effect);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_add_effect_with_name (ClutterActor *self,
|
||||
const gchar *name,
|
||||
ClutterEffect *effect);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_effect (ClutterActor *self,
|
||||
ClutterEffect *effect);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_remove_effect_by_name (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_actor_get_effects (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
ClutterEffect *clutter_actor_get_effect (ClutterActor *self,
|
||||
const gchar *name);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_clear_effects (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_effects (ClutterActor *self);
|
||||
|
||||
G_END_DECLS
|
40
mutter/clutter/clutter/clutter-enum-types.c.in
Normal file
40
mutter/clutter/clutter/clutter-enum-types.c.in
Normal file
@ -0,0 +1,40 @@
|
||||
/*** BEGIN file-header ***/
|
||||
#include "config.h"
|
||||
#include "clutter/clutter-enum-types.h"
|
||||
/*** END file-header ***/
|
||||
|
||||
/*** BEGIN file-production ***/
|
||||
|
||||
/* enumerations from "@filename@" */
|
||||
#include "@filename@"
|
||||
|
||||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN value-header ***/
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
{
|
||||
static size_t g_enum_type_id = 0;
|
||||
|
||||
if (g_once_init_enter (&g_enum_type_id))
|
||||
{
|
||||
static const G@Type@Value values[] = {
|
||||
/*** END value-header ***/
|
||||
|
||||
/*** BEGIN value-production ***/
|
||||
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
|
||||
/*** END value-production ***/
|
||||
|
||||
/*** BEGIN value-tail ***/
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType id;
|
||||
|
||||
id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||
|
||||
g_once_init_leave (&g_enum_type_id, id);
|
||||
}
|
||||
|
||||
return g_enum_type_id;
|
||||
}
|
||||
/*** END value-tail ***/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user