Compare commits
25 Commits
citadel
...
gbsneto/of
Author | SHA1 | Date | |
---|---|---|---|
![]() |
edf8a1e399 | ||
![]() |
dd80e623a0 | ||
![]() |
5e680fd43f | ||
![]() |
4226fa50da | ||
![]() |
e5ee6e1138 | ||
![]() |
47b88de3b6 | ||
![]() |
e9b9784c5c | ||
![]() |
1135a74e3e | ||
![]() |
ae14a0a677 | ||
![]() |
dbe0602c4c | ||
![]() |
f6c57366af | ||
![]() |
6ee3ece103 | ||
![]() |
be3743ec3f | ||
![]() |
59a3075f60 | ||
![]() |
5d7edde37d | ||
![]() |
96e8074a4f | ||
![]() |
c261eb736a | ||
![]() |
03be5ed9f1 | ||
![]() |
6f0719b3c7 | ||
![]() |
6be6f04456 | ||
![]() |
e0a8e824b3 | ||
![]() |
0d51678bbe | ||
![]() |
35af306acc | ||
![]() |
e8f9d093b1 | ||
![]() |
0f1289e534 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -103,4 +103,3 @@ doc/reference/meta.types
|
||||
.dirstamp
|
||||
**/tags.*
|
||||
build/
|
||||
subprojects/sysprof/
|
||||
|
369
.gitlab-ci.yml
369
.gitlab-ci.yml
@ -1,372 +1,111 @@
|
||||
include:
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/fedora.yml'
|
||||
- remote: 'https://gitlab.freedesktop.org/freedesktop/ci-templates/-/raw/bbe5232986c9b98eb1efe62484e07216f7d1a4df/templates/ci-fairy.yml'
|
||||
image: registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
|
||||
stages:
|
||||
- review
|
||||
- prepare
|
||||
- code-review
|
||||
- build
|
||||
- test
|
||||
- analyze
|
||||
- deploy
|
||||
|
||||
variables:
|
||||
FDO_UPSTREAM_REPO: GNOME/mutter
|
||||
|
||||
.mutter.fedora:34@common:
|
||||
variables:
|
||||
FDO_DISTRIBUTION_VERSION: 34
|
||||
BASE_TAG: '2021-09-04.1'
|
||||
FDO_DISTRIBUTION_PACKAGES:
|
||||
asciidoc
|
||||
clang
|
||||
gcovr
|
||||
gdm
|
||||
gnome-shell
|
||||
python3-dbusmock
|
||||
sassc
|
||||
uncrustify
|
||||
xorg-x11-server-Xvfb
|
||||
|
||||
FDO_DISTRIBUTION_EXEC: |
|
||||
dnf install -y 'dnf-command(builddep)' &&
|
||||
|
||||
dnf builddep -y mutter --setopt=install_weak_deps=False &&
|
||||
dnf builddep -y gnome-shell --setopt=install_weak_deps=False &&
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/glib.git \
|
||||
main . 02742ef957b532789c003eef80ec7f51c370e3d5 &&
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas.git \
|
||||
41.alpha . &&
|
||||
|
||||
./.gitlab-ci/install-meson-project.sh \
|
||||
https://gitlab.gnome.org/GNOME/gjs.git \
|
||||
1.69.2 . &&
|
||||
|
||||
rpm -e --nodeps gnome-bluetooth-libs-devel \
|
||||
mutter mutter-devel \
|
||||
gnome-shell &&
|
||||
|
||||
dnf clean all
|
||||
|
||||
default:
|
||||
# Cancel jobs if newer commits are pushed to the branch
|
||||
interruptible: true
|
||||
# Auto-retry jobs in case of infra failures
|
||||
retry:
|
||||
max: 1
|
||||
when:
|
||||
- 'runner_system_failure'
|
||||
- 'stuck_or_timeout_failure'
|
||||
- 'scheduler_failure'
|
||||
- 'api_failure'
|
||||
|
||||
.mutter.fedora:34@x86_64:
|
||||
extends: .mutter.fedora:34@common
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "x86_64-${BASE_TAG}"
|
||||
|
||||
.mutter.fedora:34@aarch64:
|
||||
extends: .mutter.fedora:34@common
|
||||
variables:
|
||||
FDO_DISTRIBUTION_TAG: "aarch64-${BASE_TAG}"
|
||||
tags:
|
||||
- aarch64
|
||||
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_MERGE_REQUEST_IID'
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
- if: '$CI_COMMIT_BRANCH'
|
||||
|
||||
.pipline-guard: &pipline-guard
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
- if: '$CI_COMMIT_BRANCH =~ /^gnome-[0-9-]+$/'
|
||||
- when: 'manual'
|
||||
- coverage
|
||||
|
||||
check-commit-log:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: review
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
script:
|
||||
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
|
||||
then
|
||||
ci-fairy check-commits --junit-xml=commit-message-junit-report.xml ;
|
||||
else
|
||||
echo "Not a merge request" ;
|
||||
fi
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- commit-message-junit-report.xml
|
||||
reports:
|
||||
junit: commit-message-junit-report.xml
|
||||
<<: *pipline-guard
|
||||
- ./.gitlab-ci/check-commit-log.sh
|
||||
only:
|
||||
- merge_requests
|
||||
|
||||
check-merge-request:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: review
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
|
||||
then
|
||||
ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request-report.xml ;
|
||||
else
|
||||
echo "Not a merge request" ;
|
||||
fi
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- check-merge-request-report.xml
|
||||
reports:
|
||||
junit: check-merge-request-report.xml
|
||||
<<: *pipline-guard
|
||||
|
||||
build-fedora-container@x86_64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@x86_64
|
||||
- .mutter.fedora:34@x86_64
|
||||
stage: prepare
|
||||
needs:
|
||||
- check-commit-log
|
||||
- check-merge-request
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
|
||||
build-fedora-container@aarch64:
|
||||
extends:
|
||||
- .fdo.container-build@fedora@aarch64
|
||||
- .mutter.fedora:34@aarch64
|
||||
stage: prepare
|
||||
needs:
|
||||
- check-commit-log
|
||||
- check-merge-request
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
|
||||
check-code-style:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
stage: code-review
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
script:
|
||||
- if [[ x"$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" != "x" ]] ;
|
||||
then
|
||||
git remote add target $CI_MERGE_REQUEST_PROJECT_URL.git ;
|
||||
git fetch target $CI_MERGE_REQUEST_TARGET_BRANCH_NAME ;
|
||||
export common_parent_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "target/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME") <(git rev-list --first-parent HEAD) | head -1) ;
|
||||
python3 -u ./check-style.py --dry-run --sha $common_parent_sha ;
|
||||
else
|
||||
echo "Not a merge request" ;
|
||||
fi
|
||||
allow_failure: true
|
||||
|
||||
.build-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
build-mutter:
|
||||
stage: build
|
||||
script:
|
||||
- meson . build -Dbuildtype=debugoptimized -Db_coverage=true -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
|
||||
- meson compile -C build
|
||||
- meson install -C build
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- build
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
build-mutter@x86_64:
|
||||
extends:
|
||||
- .build-mutter
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
|
||||
build-mutter@aarch64:
|
||||
extends:
|
||||
- .build-mutter
|
||||
- .mutter.fedora:34@aarch64
|
||||
needs:
|
||||
- build-fedora-container@aarch64
|
||||
|
||||
build-without-opengl-and-glx@x86_64:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
build-without-opengl-and-glx:
|
||||
stage: build
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
script:
|
||||
- meson . build -Dbuildtype=debugoptimized -Dopengl=false -Dglx=false -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
|
||||
- meson compile -C build
|
||||
- meson install -C build
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
build-without-native-backend-and-wayland@x86_64:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
build-without-native-backend-and-wayland:
|
||||
stage: build
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
script:
|
||||
- meson . build -Dbuildtype=debugoptimized -Dnative_backend=false -Dudev=false -Dwayland=false -Dcore_tests=false -Dnative_tests=false --werror --prefix /usr
|
||||
- meson compile -C build
|
||||
- meson install -C build
|
||||
- meson . build -Dbuildtype=debugoptimized -Dnative_backend=false -Dudev=false -Dwayland=false -Dcore_tests=false --werror --prefix /usr
|
||||
- ninja -C build
|
||||
- ninja -C build install
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
.test-setup: &test-setup
|
||||
test-mutter:
|
||||
stage: test
|
||||
dependencies:
|
||||
- build-mutter
|
||||
variables:
|
||||
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
|
||||
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
|
||||
MUTTER_DEBUG_DUMMY_MODE_SPECS: "800x600@10.0"
|
||||
PIPEWIRE_DEBUG: 2
|
||||
PIPEWIRE_LOG: "$CI_PROJECT_DIR/build/meson-logs/pipewire.log"
|
||||
XVFB_SERVER_ARGS: "+iglx -noreset"
|
||||
G_SLICE: "always-malloc"
|
||||
MALLOC_CHECK_: "3"
|
||||
NO_AT_BRIDGE: "1"
|
||||
before_script:
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
# Disable e.g. audio support to not dead lock screen cast tests
|
||||
- rm -f /usr/share/pipewire/media-session.d/with-*
|
||||
- mkdir -m 700 $XDG_RUNTIME_DIR
|
||||
- pipewire & sleep 2
|
||||
|
||||
.test-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
<<: *test-setup
|
||||
stage: test
|
||||
script:
|
||||
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS"
|
||||
catchsegv meson test -C build --no-rebuild -t 10
|
||||
- dconf update
|
||||
- mkdir -m 700 $XDG_RUNTIME_DIR
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
- >
|
||||
dbus-run-session -- xvfb-run -s '+iglx -noreset'
|
||||
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
reports:
|
||||
junit: "build/meson-logs/testlog-catchsegv.junit.xml"
|
||||
name: "mutter-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
||||
test-mutter@x86_64:
|
||||
extends:
|
||||
- .test-mutter
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
|
||||
test-mutter@aarch64:
|
||||
extends:
|
||||
- .test-mutter
|
||||
- .mutter.fedora:34@aarch64
|
||||
needs:
|
||||
- build-mutter@aarch64
|
||||
|
||||
.test-mutter-coverage:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
stage: analyze
|
||||
test-mutter-coverage:
|
||||
stage: coverage
|
||||
dependencies:
|
||||
- test-mutter
|
||||
script:
|
||||
- ninja -C build coverage
|
||||
- cat build/meson-logs/coverage.txt
|
||||
artifacts:
|
||||
paths:
|
||||
- build/meson-logs/coveragereport
|
||||
coverage: '/^TOTAL.*\s+(\d+\%)$/'
|
||||
- build/meson-logs
|
||||
when: manual
|
||||
except:
|
||||
refs:
|
||||
- tags
|
||||
- master
|
||||
|
||||
test-mutter-coverage@x86_64:
|
||||
extends:
|
||||
- .test-mutter-coverage
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- test-mutter@x86_64
|
||||
|
||||
test-mutter-coverage@aarch64:
|
||||
extends:
|
||||
- .test-mutter-coverage
|
||||
- .mutter.fedora:34@aarch64
|
||||
needs:
|
||||
- test-mutter@aarch64
|
||||
|
||||
can-build-gnome-shell@x86_64:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
can-build-gnome-shell:
|
||||
stage: test
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
dependencies:
|
||||
- build-mutter
|
||||
before_script:
|
||||
- meson install --no-rebuild -C build
|
||||
script:
|
||||
- .gitlab-ci/checkout-gnome-shell.sh
|
||||
- meson gnome-shell gnome-shell/build --prefix /usr -Dman=false
|
||||
- meson install -C gnome-shell/build
|
||||
|
||||
test-mutter-coverity:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "schedule" && $MUTTER_SCHEDULED_JOB == "coverity"'
|
||||
when: always
|
||||
- when: manual
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
needs:
|
||||
- build-fedora-container@x86_64
|
||||
stage: analyze
|
||||
allow_failure: true
|
||||
script:
|
||||
- .gitlab-ci/download-coverity-tarball.sh
|
||||
- CC=clang meson coverity-build -Dprofiler=false
|
||||
- ./coverity/cov-analysis-linux64-*/bin/cov-build --dir cov-int meson compile -C coverity-build
|
||||
- tar czf cov-int.tar.gz cov-int
|
||||
- curl https://scan.coverity.com/builds?project=mutter
|
||||
--form token=$COVERITY_TOKEN --form email=carlosg@gnome.org
|
||||
--form file=@cov-int.tar.gz --form version="`git describe --tags`"
|
||||
--form description="GitLab CI build"
|
||||
cache:
|
||||
key: coverity-tarball
|
||||
paths:
|
||||
- coverity
|
||||
|
||||
dist-mutter:
|
||||
extends:
|
||||
- .fdo.distribution-image@fedora
|
||||
- .mutter.fedora:34@x86_64
|
||||
<<: *test-setup
|
||||
stage: deploy
|
||||
needs:
|
||||
- build-mutter@x86_64
|
||||
script:
|
||||
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS" meson dist -C build
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
changes:
|
||||
- "**/meson.build"
|
||||
- meson/*
|
||||
|
||||
dist-mutter-tarball:
|
||||
extends: dist-mutter
|
||||
artifacts:
|
||||
expose_as: 'Get tarball here'
|
||||
paths:
|
||||
- build/meson-dist/$CI_PROJECT_NAME-$CI_COMMIT_TAG.tar.xz
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG'
|
||||
- ninja -C gnome-shell/build install
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
27
.gitlab-ci/Dockerfile
Normal file
27
.gitlab-ci/Dockerfile
Normal file
@ -0,0 +1,27 @@
|
||||
# Rebuild and push with
|
||||
#
|
||||
# cd .gitlab-ci/
|
||||
# podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v4 .
|
||||
# podman push registry.gitlab.gnome.org/gnome/mutter/master:v4
|
||||
#
|
||||
|
||||
FROM fedora:32
|
||||
|
||||
RUN dnf -y update && dnf -y upgrade && \
|
||||
dnf install -y 'dnf-command(builddep)' && \
|
||||
dnf install -y 'dnf-command(copr)' && \
|
||||
dnf copr enable -y jadahl/mutter-ci && \
|
||||
|
||||
dnf builddep -y mutter --setopt=install_weak_deps=False && \
|
||||
|
||||
# For running unit tests
|
||||
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 \
|
||||
'*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center gcovr \
|
||||
--setopt=install_weak_deps=False && \
|
||||
|
||||
# GNOME Shell
|
||||
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
|
||||
dnf remove -y gnome-bluetooth-libs-devel && \
|
||||
dnf remove -y --noautoremove mutter mutter-devel && \
|
||||
|
||||
dnf clean all
|
60
.gitlab-ci/check-commit-log.sh
Executable file
60
.gitlab-ci/check-commit-log.sh
Executable file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
echo Cannot review non-merge request
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
|
||||
branch_point=$(git merge-base HEAD FETCH_HEAD)
|
||||
|
||||
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
|
||||
|
||||
if [ -z "$commits" ]; then
|
||||
echo Commit range empty
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function commit_message_has_url() {
|
||||
commit=$1
|
||||
commit_message=$(git show -s --format='format:%b' $commit)
|
||||
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(-/\)\?\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
|
||||
return $?
|
||||
}
|
||||
|
||||
function commit_message_subject_is_compliant() {
|
||||
commit=$1
|
||||
commit_message_subject=$(git show -s --format='format:%s' $commit)
|
||||
|
||||
if echo "$commit_message_subject" | grep -qe "\(^meta-\|^Meta\)"; then
|
||||
echo " - message subject should not be prefixed with 'meta-' or 'Meta'"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if echo "$commit_message_subject" | grep -qe "\.[ch]:"; then
|
||||
echo " - message subject prefix should not include .c, .h, etc."
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
RET=0
|
||||
for commit in $commits; do
|
||||
commit_short=$(echo $commit | cut -c -8)
|
||||
|
||||
if ! commit_message_has_url $commit; then
|
||||
echo "Commit $commit_short needs a merge request or issue URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
errors=$(commit_message_subject_is_compliant $commit)
|
||||
if [ $? != 0 ]; then
|
||||
echo "Commit message for $commit_short is not compliant:"
|
||||
echo "$errors"
|
||||
RET=1
|
||||
fi
|
||||
done
|
||||
|
||||
exit $RET
|
@ -1,19 +1,11 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
fetch() {
|
||||
local remote=$1
|
||||
local ref=$2
|
||||
|
||||
git fetch --quiet --depth=1 $remote $ref 2>/dev/null
|
||||
}
|
||||
|
||||
gnome_shell_target=
|
||||
|
||||
echo -n Cloning into gnome-shell ...
|
||||
if git clone --quiet --depth=1 https://gitlab.gnome.org/GNOME/gnome-shell.git; then
|
||||
echo \ done
|
||||
else
|
||||
echo \ failed
|
||||
git clone https://gitlab.gnome.org/GNOME/gnome-shell.git
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo Checkout failed
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@ -23,33 +15,19 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//mutter/gnome-shell}
|
||||
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
||||
|
||||
echo -n Looking for $merge_request_branch on remote ...
|
||||
if fetch $merge_request_remote $merge_request_branch; then
|
||||
echo \ found
|
||||
echo Looking for $merge_request_branch on remote ...
|
||||
if git fetch -q $merge_request_remote $merge_request_branch 2>/dev/null; then
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
|
||||
echo -n Looking for $CI_MERGE_REQUEST_TARGET_BRANCH_NAME instead ...
|
||||
if fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME; then
|
||||
echo \ found
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$gnome_shell_target" ]; then
|
||||
echo -n Looking for $CI_COMMIT_REF_NAME on remote ...
|
||||
if fetch origin $CI_COMMIT_REF_NAME; then
|
||||
echo \ found
|
||||
gnome_shell_target=FETCH_HEAD
|
||||
else
|
||||
echo \ not found
|
||||
gnome_shell_target=HEAD
|
||||
gnome_shell_target=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
||||
echo Using $gnome_shell_target instead
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$gnome_shell_target" ]; then
|
||||
gnome_shell_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
|
||||
gnome_shell_target=${gnome_shell_target:-origin/master}
|
||||
echo Using $gnome_shell_target instead
|
||||
fi
|
||||
|
||||
git checkout -q $gnome_shell_target
|
||||
|
@ -1,19 +0,0 @@
|
||||
patterns:
|
||||
deny:
|
||||
- regex: '^$CI_MERGE_REQUEST_PROJECT_URL/(-/)?merge_requests/$CI_MERGE_REQUEST_IID$'
|
||||
message: Commit message must not contain a link to its own merge request
|
||||
- regex: '^(meta-|Meta)'
|
||||
message: Commit message subject should not be prefixed with 'meta-' or 'Meta'
|
||||
where: subject
|
||||
- regex: '^(clutter-|Clutter)'
|
||||
message: Commit message subject should not be prefixed with 'clutter-' or 'Clutter', use 'clutter/' instead
|
||||
where: subject
|
||||
- regex: '^(cogl-|Cogl)'
|
||||
message: Commit message subject should not be prefixed with 'cogl-' or 'Cogl', use 'cogl/' instead
|
||||
where: subject
|
||||
- regex: '^[^:]+: [a-z]'
|
||||
message: "Commit message subject should be properly Capitalized. E.g. 'window: Marginalize extradicity'"
|
||||
where: subject
|
||||
- regex: '^\S*\.[ch]:'
|
||||
message: Commit message subject prefix should not include .c, .h, etc.
|
||||
where: subject
|
@ -1,38 +0,0 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# We need a coverity token to fetch the tarball
|
||||
if [ -x $COVERITY_TOKEN ]
|
||||
then
|
||||
echo "No coverity token. Run this job from a protected branch."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
mkdir -p coverity
|
||||
|
||||
# Download and check MD5 first
|
||||
curl https://scan.coverity.com/download/linux64 \
|
||||
--data "token=$COVERITY_TOKEN&project=mutter&md5=1" \
|
||||
--output /tmp/coverity_tool.md5
|
||||
|
||||
diff /tmp/coverity_tool.md5 coverity/coverity_tool.md5 >/dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 -a -d coverity/cov-analysis* ]
|
||||
then
|
||||
echo "Coverity tarball is up-to-date"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Download and extract coverity tarball
|
||||
curl https://scan.coverity.com/download/linux64 \
|
||||
--data "token=$COVERITY_TOKEN&project=mutter" \
|
||||
--output /tmp/coverity_tool.tgz
|
||||
|
||||
rm -rf ./coverity/cov-analysis*
|
||||
|
||||
tar zxf /tmp/coverity_tool.tgz -C coverity/
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
mv /tmp/coverity_tool.md5 coverity/
|
||||
fi
|
||||
|
||||
rm /tmp/coverity_tool.tgz
|
@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [[ $# -lt 3 ]]; then
|
||||
echo Usage: $0 [options] [repo-url] [commit] [subdir]
|
||||
echo Options:
|
||||
echo -Dkey=val
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MESON_OPTIONS=()
|
||||
|
||||
while [[ $1 =~ ^-D ]]; do
|
||||
MESON_OPTIONS+=( "$1" )
|
||||
shift
|
||||
done
|
||||
|
||||
REPO_URL="$1"
|
||||
TAG_OR_BRANCH="$2"
|
||||
SUBDIR="$3"
|
||||
COMMIT="$4"
|
||||
|
||||
REPO_DIR="$(basename ${REPO_URL%.git})"
|
||||
|
||||
git clone --depth 1 "$REPO_URL" -b "$TAG_OR_BRANCH"
|
||||
pushd "$REPO_DIR"
|
||||
pushd "$SUBDIR"
|
||||
|
||||
if [ ! -z "$COMMIT" ]; then
|
||||
git fetch origin "$COMMIT"
|
||||
git checkout "$COMMIT"
|
||||
fi
|
||||
|
||||
meson --prefix=/usr _build "${MESON_OPTIONS[@]}"
|
||||
meson install -C _build
|
||||
popd
|
||||
popd
|
||||
rm -rf "$REPO_DIR"
|
286
HACKING.md
286
HACKING.md
@ -1,286 +0,0 @@
|
||||
# Style
|
||||
|
||||
The coding style used is primarily the GNU flavor of the [GNOME coding
|
||||
style][gnome-coding-style], with some additions described below.
|
||||
|
||||
## General
|
||||
|
||||
* Use this code style on new code. When changing old code with a different
|
||||
code style, feel free to also adjust it to use this code style.
|
||||
|
||||
* Use regular C types and `stdint.h` types instead of GLib fundamental
|
||||
types, except for `gboolean`, and `guint`/`gulong` for GSource IDs and
|
||||
signal handler IDs. That means e.g. `uint64_t` instead of `guint64`, `int`
|
||||
instead of `gint`, `unsigned int` instead of `guint` if unsignedness
|
||||
is of importance, `uint8_t` instead of `guchar`, and so on.
|
||||
|
||||
* Try to to limit line length to 80 characters, although it's not a
|
||||
strict limit.
|
||||
|
||||
* Usage of `g_autofree` and `g_autoptr` is encouraged. The style to use is
|
||||
|
||||
```c
|
||||
g_autofree char *text = NULL;
|
||||
g_autoptr (MetaSomeThing) thing = NULL;
|
||||
|
||||
text = g_strdup_printf ("The text: %d", a_number);
|
||||
thing = g_object_new (META_TYPE_SOME_THING,
|
||||
"text", text,
|
||||
NULL);
|
||||
thinger_use_thing (rocket, thing);
|
||||
```
|
||||
|
||||
* Declare variables at the top of the block they are used, but avoid
|
||||
non-trivial logic among variable declarations. Non-trivial logic can be
|
||||
getting a pointer that may be `NULL`, any kind of math, or anything
|
||||
that may have side effects.
|
||||
|
||||
* Instead of boolean arguments in functions, prefer enums or flags when
|
||||
they're more expressive. The naming convention for flags is
|
||||
|
||||
```c
|
||||
typedef _MetaSomeThingFlags
|
||||
{
|
||||
META_SOME_THING_FLAG_NONE = 0,
|
||||
META_SOME_THING_FLAG_ALTER_REALITY = 1 << 0,
|
||||
META_SOME_THING_FLAG_MANIPULATE_PERCEPTION = 1 << 1,
|
||||
} MetaSomeThingFlags;
|
||||
```
|
||||
|
||||
* Use `g_new0 ()` etc. instead of `g_slice_new0 ()`.
|
||||
|
||||
* Initialize and assign floating point variables (i.e. `float` or
|
||||
`double`) using the form `floating_point = 3.14159` or `ratio = 2.0`.
|
||||
|
||||
## Header (.h) files
|
||||
|
||||
* The return type and `*` are separated by a space.
|
||||
* Function name starts one space after the last `*`.
|
||||
* Parenthesis comes one space after the function name.
|
||||
|
||||
As an example, this is how functions in a header file should look like:
|
||||
|
||||
```c
|
||||
gboolean meta_udev_is_drm_device (MetaUdev *udev,
|
||||
GUdevDevice *device);
|
||||
|
||||
GList * meta_udev_list_drm_devices (MetaUdev *udev,
|
||||
GError **error);
|
||||
|
||||
MetaUdev * meta_udev_new (MetaBackendNative *backend_native);
|
||||
```
|
||||
|
||||
## Source code
|
||||
|
||||
Keep functions in the following order in source files:
|
||||
|
||||
1. GPL header
|
||||
2. Enums
|
||||
3. Structures
|
||||
4. Function prototypes
|
||||
5. `G_DEFINE_TYPE()`
|
||||
6. Static variables
|
||||
7. Auxiliary functions
|
||||
8. Callbacks
|
||||
9. Interface implementations
|
||||
10. Parent vfunc overrides
|
||||
11. class_init and init
|
||||
12. Public API
|
||||
|
||||
### Structures
|
||||
|
||||
Each structure field has a space after their type name. Structure fields aren't
|
||||
aligned. For example:
|
||||
|
||||
```c
|
||||
struct _MetaFooBar
|
||||
{
|
||||
MetaFoo parent;
|
||||
|
||||
MetaBar *bar;
|
||||
MetaSomething *something;
|
||||
};
|
||||
```
|
||||
|
||||
### Function Prototypes
|
||||
|
||||
Function prototypes must be formatted just like in header files.
|
||||
|
||||
### Overrides
|
||||
|
||||
When overriding parent class vfuncs, or implementing an interface, vfunc
|
||||
overrides should be named as a composition of the current class prefix,
|
||||
followed by the vfunc name. For example:
|
||||
|
||||
|
||||
```c
|
||||
static void
|
||||
meta_bar_spawn_unicorn (MetaParent *parent)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_bar_dispose (GObject *object)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_bar_finalize (GObject *object)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_bar_class_init (MetaBarClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaParentClass *parent_class = META_PARENT_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_bar_dispose;
|
||||
object_class->finalize = meta_bar_finalize;
|
||||
|
||||
parent_class->spawn_unicorn = meta_bar_spawn_unicorn;
|
||||
}
|
||||
```
|
||||
|
||||
### Interface Implementations
|
||||
|
||||
When implementing interfaces, two groups of functions are involved: the init
|
||||
function, and the overrides.
|
||||
|
||||
The interface init function is named after the interface type in snake case,
|
||||
followed by the `_iface_init` suffix. For example:
|
||||
|
||||
|
||||
```c
|
||||
static void meta_foo_iface_init (MetaFooInterface *foo_iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaBar, meta_bar, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_FOO,
|
||||
meta_foo_iface_init));
|
||||
```
|
||||
|
||||
Then, when implementing each vfunc of the interface, follow the same pattern
|
||||
of the [Overrides](###Overrides) section. Here's an example:
|
||||
|
||||
```c
|
||||
static void
|
||||
meta_bar_do_something (MetaFoo *foo)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_foo_iface_init (MetaFooInterface *foo_iface)
|
||||
{
|
||||
foo_iface->do_something = meta_bar_do_something;
|
||||
}
|
||||
```
|
||||
|
||||
### Auxiliary Functions
|
||||
|
||||
Auxiliary functions are above every other functions to minimize the number of
|
||||
function prototypes in the file. These functions often grow when factoring out
|
||||
the same code between two or more functions:
|
||||
|
||||
```c
|
||||
static void
|
||||
do_something_on_data (Foo *data,
|
||||
Bar *bar)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
random_function (Foo *foo)
|
||||
{
|
||||
do_something_on_data (foo, bar);
|
||||
}
|
||||
|
||||
static void
|
||||
another_random_function (Foo *foo)
|
||||
{
|
||||
do_something_on_data (foo, bar);
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes, however, auxiliary functions are created to break down otherwise
|
||||
large functions - in this case, it is appropriate to keep these auxiliary
|
||||
functions close to the function they are tightly related to.
|
||||
|
||||
Auxiliary function names must have a verb in the imperative form, and should
|
||||
always perform an action over something. They usually don't have the class
|
||||
prefix (`meta_`, `clutter_`, or `cogl_`). For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
do_something_on_data (Foo *data,
|
||||
Bar *bar)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
Exceptionally, when converting between types, auxiliary function names may
|
||||
have the class prefix to this rule. For example:
|
||||
|
||||
```c
|
||||
static MetaFoo *
|
||||
meta_foo_from_bar (Bar *bar)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### Callback Functions
|
||||
|
||||
Callback function names should have the name of the action in imperative
|
||||
form. They don't have any prefix, but have a `_func` suffix. For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
filter_something_func (Foo *foo,
|
||||
Bar *bar,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
### Signal Callbacks
|
||||
|
||||
Signal callbacks generally have the signal name. They should be prefixed with
|
||||
`on_`, or suffixed with `_cb`, but not both. For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
on_realize (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_cb (ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
When the callback is named after the object that generated it, and the signal,
|
||||
then passive voice is used. For example:
|
||||
|
||||
```c
|
||||
static void
|
||||
click_action_clicked_cb (ClutterClickAction *click_action,
|
||||
ClutterActor *actor,
|
||||
gpointer user_data)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
```
|
||||
|
||||
[gnome-coding-style]: https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en
|
517
NEWS
517
NEWS
@ -1,494 +1,3 @@
|
||||
41.1
|
||||
====
|
||||
* Fix monitor screencast scanouts [Michel; !1914]
|
||||
* dma-buf: Use alpha-less pixel formats where appropriate [Robert; !1810]
|
||||
* wayland: Allow clients to maximize windows regardless of constraints
|
||||
[Christian; !1997]
|
||||
* Handle hotplug events without relevant changes more effectively
|
||||
[Marco; !1964]
|
||||
* Improve error reporting when startup fails [Jonas; !1994]
|
||||
* dma-buf: Add support for ABGR and XBGR formats [Erfan; !1999]
|
||||
* Fix X11 middle button emulation setting [José; !2000]
|
||||
* Include server-side shadows in window screenshots [Robert; !1996]
|
||||
* Don't change workspaces of unmanaged windows [Sebastian; !2003]
|
||||
* Reset idletime when unplugging the power cable [Bastien; !2029]
|
||||
* xwayland: Avoid unnecessary _NET_WM_STATE events [Dor; !2032]
|
||||
* Fix videos in Firefox stuttering in overview [Robert; !2034]
|
||||
* Don't use atomic mode setting for virtio_gpu driver [Jonas; !2040]
|
||||
* Improve on-screen keyboard on X11 [Sebastian, Ray; !1955, !2039]
|
||||
* misc [Daniel, Jonas, Corentin, Robert; !1992, !2007, !2008, !2026, !2044]
|
||||
* Fix text glitches after size changes [Sebastian; !2006]
|
||||
* Fix reporting output rotation to xwayland [Olivier; !2050]
|
||||
* wayland: Accept final preference of drop destination [Robert; !2043]
|
||||
* Fix erratic scrolling in GTK apps [Carlos; gnome-shell#4647]
|
||||
* Fix tilt direction of pen/tablet inputs [Quytelda; !2065]
|
||||
* Use b/w unicode for tablet mode OSD [Carlos; !2064]
|
||||
* Fix negative paint volume offscreen effect [Sebastian; !2031]
|
||||
* Only add paint volumes of mapped actors to stage clip [Robert; !2035]
|
||||
* Fix mapping tablet input to correct monitor [Jason; !1934]
|
||||
* Misc. bug fixes and cleanups
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Erfan Abdi, Dor Askayo, Michel Dänzer,
|
||||
José Expósito, Olivier Fourdan, Carlos Garnacho, Jason Gerecke,
|
||||
Quytelda Kahja, Sebastian Keller, Robert Mader, Bastien Nocera, Corentin Noël,
|
||||
Christian Rauch, Ray Strode, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
eshagh shahidani [fa], Danial Behzadi [fa], Марко Костић [sr],
|
||||
Zander Brown [en_GB], Ngọc Quân Trần [vi], Rūdolfs Mazurs [lv]
|
||||
|
||||
41.0
|
||||
====
|
||||
* Avoid race in wl_seat capabilities [Olivier; !77]
|
||||
* Expose option groups/entries to introspection [Corentin; !1976]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan, Corentin Noël
|
||||
|
||||
Translators:
|
||||
Daniel Șerbănescu [ro], Goran Vidović [hr], Luna Jernberg [sv],
|
||||
eshagh shahidani [fa], Gwan-gyeong Mun [ko], Emin Tufan Çetin [tr],
|
||||
Philipp Kiemle [de], Balázs Úr [hu], Piotr Drąg [pl], Nathan Follens [nl],
|
||||
Jordi Mas [ca], Ask Hjorth Larsen [da]
|
||||
|
||||
41.rc
|
||||
=====
|
||||
* Add clutter_stage_paint_to_content() [Ivan; !1899]
|
||||
* Add meta_cursor_tracker_get_scale() [Ivan; !1967]
|
||||
* wayland: Make each wl_output correspond to one monitor [Jonas; !1712]
|
||||
* Expose 'inactive-since' timestamp to uresourced [Nishal; !1960]
|
||||
* Pass dirty rects to secondary GPU [Piotr; !1879]
|
||||
* Support commiting preedit string on focus loss [Carlos; !1940]
|
||||
* Improve auto-rotation support [Marco; !1233]
|
||||
* Add meta_window_actor_paint_to_content() [Robert; !1893]
|
||||
* Fixed crashes [Jonas, Ray, Robert; !1947, !1979, !1965, !1958]
|
||||
* Misc. bug fixes and cleanups [Florian, Carlos, Robert, Daniel, Erico, Dor;
|
||||
!1957, !1924, !1970, !1971, !1972, !1973, !1974, !1977, !1978, !1975, !1886,
|
||||
!1983, !1990, !1980]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Dor Askayo, Carlos Garnacho, Nishal Kulkarni,
|
||||
Piotr Lopatka, Robert Mader, Ivan Molodetskikh, Florian Müllner, Erico Nunes,
|
||||
Ray Strode, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Asier Sarasua Garmendia [eu], Claude Paroz [fr], Jiri Grönroos [fi],
|
||||
Baurzhan Muftakhidinov [kk], Aurimas Černius [lt]
|
||||
|
||||
41.beta
|
||||
=======
|
||||
* Fix mouse position in remote desktop with fractional scaling [Pascal; !1867]
|
||||
* Manage idle monitors via MetaIdleManager [Jonas Å.; !1859]
|
||||
* Disable KMS modifiers on radeon driver [Carlos; !1872]
|
||||
* Fix fd leak [Carlos; !1870]
|
||||
* Fix adding virtual monitor to physical session [Jonas Å.; !1891]
|
||||
* Unbreak press-drag-release to pop up and select right click menus
|
||||
[Carlos; !1885]
|
||||
* Fix VKMS detection [Jonas Å.; !1892]
|
||||
* Fix swipe cancellation [JoseExposito; !1857]
|
||||
* Add ClutterTextureContent [Robert; !1888]
|
||||
* Fix mapping tablet to monitor [Christoph; !1887]
|
||||
* Fix area screencasts when window is unredirected [Michel; !1902]
|
||||
* Don't require a newly attached buffer to apply state [Christian, Jonas; !1795]
|
||||
* Close unused mode setting and rendering devices [Jonas Å.; !1828]
|
||||
* Only support super+scroll on wayland [Florian; !1922]
|
||||
* Implement the xdg-activation protocol [Carlos; !1845]
|
||||
* Reduce input latency by computing max render time heuristically [Ivan; !1762]
|
||||
* Apply dithering to dispatch time when needed [Daniel; !1826]
|
||||
* Introduce MetaContext [Jonas Å.; !1861]
|
||||
* x11: Compute monitor scale per output [Marco; !336]
|
||||
* Shrink and optimize the rounded-background-clip shader [Daniel; !1860]
|
||||
* remote-desktop: Handle non-responding selection owners [Pascal; !1874]
|
||||
* Improve sysprof support [Jonas Å.; !1700]
|
||||
* Allow clients to delegate titlebar gestures to the compositor [Florian; !1944]
|
||||
* Fix upside-down Xshape surface with EGLstream [Robert; !1937]
|
||||
* Fix 'kms-modifiers' experimental setting [Robert; !1953]
|
||||
* Make default focus window on each workspace appear focused [Alexander; !850]
|
||||
* Plugged memory leaks [Jonas Å.; !1869]
|
||||
* Fixed crashes crash [Daniel, Jonas Å., Florian; !1883, !1895,
|
||||
!1910, !1925, !1956]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Marco, Daniel, Florian, Georges,
|
||||
Zander, Carlos, Robert; !1833, !1863, !1876, !1873, !1884, !1890, !1900,
|
||||
!1912, !1916, !1911, !1920, !1865, !1927, !1923, !1929, !1100, !1932, !1931,
|
||||
!1862, !1933, !1930, !1935, !1936, !1878, !1938, !1942, !1951, !522, !1941]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Zander Brown, Piotr Drąg, Michel Dänzer,
|
||||
Carlos Garnacho, JoseExposito, Robert Mader, Alexander Mikhaylenko,
|
||||
Ivan Molodetskikh, Florian Müllner, Georges Basile Stavracas Neto,
|
||||
Pascal Nowack, Christian Rauch, Christoph Trassl, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Pawan Chitrakar [ne], Charles Monzat [fr], Dušan Kazik [sk],
|
||||
Quentin PAGÈS [oc], Alexey Rubtsov [ru], Alexander Shopov [bg],
|
||||
Florentina Mușat [ro], Chao-Hsiung Liao [zh_TW], Yuri Chornoivan [uk],
|
||||
Fran Dieguez [gl], Hugo Carvalho [pt], Rafael Fontenelle [pt_BR],
|
||||
Fabio Tomat [fur], Kukuh Syafaat [id], Yaron Shahrabani [he],
|
||||
Marek Černocký [cs], Matej Urbančič [sl], Boyuan Yang [zh_CN],
|
||||
Daniel Mustieles [es]
|
||||
|
||||
40.1
|
||||
====
|
||||
* Prevent clients from pasting old selection data [Carlos; !1772]
|
||||
* Fix forward_key IM functionality on wayland [Takao; !1802]
|
||||
* Ensure valid window texture size after viewport changes [Robert; !1799]
|
||||
* Only update cached paint volumes when necessary [Jonas D.; !1773, !1829]
|
||||
* Only disable KMS modifiers for drivers with known problems [Jonas Å; !1792]
|
||||
* Fix X11 client resize during moves [Olivier; !1777]
|
||||
* Fix performance drop during night light transition with Nvidia [Aaron; !1816]
|
||||
* kms: Don't add common modes that exceed the max bandwidth [Jonas Å.; !1834]
|
||||
* Create virtual input devices on demand [Jonas Å; !1800, !1858]
|
||||
* Fix wrong night light gamma when leaving power saving [Jonas Å.; !1835]
|
||||
* Fix picking edge case [Sebastian; !1842]
|
||||
* Properly tear down things when shutting down [Jonas Å.; !1822, !1856, !1853]
|
||||
* Fix monitor screencasting with fractional scaling [kirbykevinson; !1855]
|
||||
* Fixed crash [Carlos; !1849]
|
||||
* Plugged memory leak [Carlos; !1839]
|
||||
* Misc. bug fixes and cleanups [Carlos, Daniel, Jonas D., Jonas Å., Robert,
|
||||
Aleksandr, Florian, Michel, Sebastian, Olivier; !1785, !1798, !1784,
|
||||
!1791, !1801, !1807, !1786, !1793, !1804, !1820, !1824, !1819, !1803,
|
||||
!1821, !1806, !1814, !1831, !1832, !1836, !1843, !1740, !1841, !1827,
|
||||
!1844, !1852, !1850, !1851]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Michel Dänzer, Jonas Dreßler, Olivier Fourdan, Takao Fujiwara,
|
||||
Carlos Garnacho, Sebastian Keller, kirbykevinson, Robert Mader,
|
||||
Aleksandr Mezin, Florian Müllner, Aaron Plattner, Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Bruce Cowan [en_GB], Ngọc Quân Trần [vi], Marek Černocký [cs],
|
||||
Dz Chen [zh_CN], Yosef Or Boczko [he], Nathan Follens [nl],
|
||||
Yuri Chornoivan [uk], Jordi Mas [ca], Piotr Drąg [pl], Tim Sabsch [de],
|
||||
Luna Jernberg [sv], Hugo Carvalho [pt], Rafael Fontenelle [pt_BR],
|
||||
Asier Sarasua Garmendia [eu], Quentin PAGÈS [oc], Matej Urbančič [sl]
|
||||
|
||||
40.0
|
||||
====
|
||||
* xwayland: Check permissions on /tmp/.X11-unix [Olivier; !1787]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan
|
||||
|
||||
Translators:
|
||||
Hugo Carvalho [pt], Tim Sabsch [de], Daniel Mustieles [es],
|
||||
Matej Urbančič [sl], Марко Костић [sr], Fran Dieguez [gl]
|
||||
|
||||
40.rc
|
||||
=====
|
||||
* Fix keyboard input from remote desktop in Xorg session [Pascal; !1732]
|
||||
* Fix restoring focus to windows using globally active input [Olivier; !1716]
|
||||
* Expose unaccalerated touchpad gesture deltas [Alexander; !1353]
|
||||
* Avoid relayout on text attribute changes when possible [Jonas D.; !1750]
|
||||
* Add remote desktop caps- and num-lock state properties [Jonas Å.; !1739]
|
||||
* Improve refresh rate calculation [Akihiko; !1737]
|
||||
* Implement presentation-time protocol [Ivan; !1484]
|
||||
* Disable double-buffered shadow buffering [Jonas Å.; !1724]
|
||||
* Fix missing cursor on tablet devices [Jonas D.; !1758]
|
||||
* Fix frame timings causing X11 clients to get stuck [Jonas Å.; !1754]
|
||||
* Fix applying input settings on X11 [Marco, Suryashankar; !1769, !1767]
|
||||
* Add headless native backend [Jonas Å.; !1698]
|
||||
* Fix high latency and stalls with proprietary nvidia driver [Daniel; !1726]
|
||||
* Fix maximized windows not reacting to strut changes [Aleksandr; !1755]
|
||||
* Only start XWayland on demand when running under systemd [Benjamin; !1771]
|
||||
* Sync LEDs when a new input device is added [Olivier; !1662]
|
||||
* Fix order in which subsurface placement operations are handled [Robert; !1768]
|
||||
* Fixed crashes [Jonas Å., Sebastian; !1745, !1747, !1759, !1748, !1776, !1775]
|
||||
* Plugged leaks [Philip, Sebastian; !1738, !1728]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Ivan, Florian, Marco,
|
||||
Robert; !1688, !1744, !1736, !1749, !1752, !1753, !427, !1757, !1751, !1760,
|
||||
!1765, !1770, !1763, !1774, !1780, !1779, !1783]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Benjamin Berg, Suryashankar Das, Jonas Dreßler, Olivier Fourdan,
|
||||
Sebastian Keller, Robert Mader, Aleksandr Mezin, Alexander Mikhaylenko,
|
||||
Ivan Molodetskikh, Florian Müllner, Pascal Nowack, Akihiko Odaki,
|
||||
Marco Trevisan (Treviño), Daniel van Vugt, Philip Withnall
|
||||
|
||||
Translators:
|
||||
Fran Dieguez [gl], Asier Sarasua Garmendia [eu], Claude Paroz [fr],
|
||||
Piotr Drąg [pl], Hugo Carvalho [pt], Jordi Mas [ca], Fabio Tomat [fur],
|
||||
Yuri Chornoivan [uk], Enrico Nicoletto [pt_BR], Emin Tufan Çetin [tr],
|
||||
Daniel Șerbănescu [ro], Marek Černocký [cs], Balázs Úr [hu],
|
||||
Aurimas Černius [lt], Kukuh Syafaat [id], A S Alam [pa], Anders Jonsson [sv],
|
||||
Milo Casagrande [it], Gwan-gyeong Mun [ko]
|
||||
|
||||
40.beta
|
||||
=======
|
||||
* Consider clients without mapped windows for xwayland auto-shutdown
|
||||
[Olivier; !1671]
|
||||
* Let compositor to handle super+scroll events [Florian; !1674, !1695]
|
||||
* Default to starting Xwayland on demand [Olivier; !1673]
|
||||
* xwayland: Restore abstract socket support [James, Olivier; !1669]
|
||||
* Add support for atomic mode setting [Jonas Å.; !1488]
|
||||
* Fix clip region glitches when using fractional scaling [Daniel; !1554]
|
||||
* Default to horizontal workspace layout [Georges, Florian; !1684, !1706]
|
||||
* Do not ping unmanaging windows [Florian; gnome-shell#2467]
|
||||
* Handle monitor changes during screencasts [Jonas Å.; !1691]
|
||||
* Fix unexpected jumps after restoring misbehaving clients [Jonas Å.; !1445]
|
||||
* Fix newly opened X11 windows being invisible in overview [Olivier; !1678]
|
||||
* Fix viewport of offscreen effects [Daniel; !1053]
|
||||
* Fix drag cancel animation when using geometry scaling [Robert; !1683]
|
||||
* Improve touch-mode heuristics [Carlos; !1710]
|
||||
* Integrate clipboard with remote desktop sessions [Jonas Å.; !1552]
|
||||
* Fix stuck icon in DND operation between X11 and wayland [Carlos; !1720]
|
||||
* Automatically synchronize pointer position after modal grabs [Carlos; !1659]
|
||||
* Reimplement support for CLUTTER_SHOW_FPS [Daniel; !154]
|
||||
* Only pick on events that may move the pointer [Jonas D.; !1729, !1733]
|
||||
* Emit discrete scroll events for accumulated smooth events in virtual
|
||||
X11 devices [Pascal; !1727]
|
||||
* Add support for rounded clipping when drawing background [Jonas D.; !1717]
|
||||
* Plugged memory leaks [Sebastian; !1307, !1699]
|
||||
* Fixed crashes [Carlos, Thomas, Jonas Å., Olivier; !1677, !1685, !1692,
|
||||
!1719, !1718, !1735]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Carlos, Olivier, Sebastian, Björn,
|
||||
Jonas D., Ivan, Georges, Dor, Michel, Robert; !1670, !1679, !1680, !1682,
|
||||
!1681, !1661, !1689, !1690, !1693, !1514, !1696, !1697, !1708, !1709, !1707,
|
||||
!1701, !1702, !1715, !1725, !1734, !1512]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Dor Askayo, Björn Daase, Michel Dänzer, Jonas Dreßler,
|
||||
Olivier Fourdan, Carlos Garnacho, James Henstridge, Sebastian Keller,
|
||||
Robert Mader, Ivan Molodetskikh, Thomas Mühlbacher, Florian Müllner,
|
||||
Georges Basile Stavracas Neto, Pascal Nowack, Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Марко Костић [sr], Jordi Mas [ca], Yuri Chornoivan [uk],
|
||||
Daniel Șerbănescu [ro], Hugo Carvalho [pt], Fran Dieguez [gl],
|
||||
Matej Urbančič [sl], Marek Černocký [cs], Rafael Fontenelle [pt_BR],
|
||||
Philipp Kiemle [de], A S Alam [pa], Balázs Úr [hu], Anders Jonsson [sv],
|
||||
Daniel Mustieles [es], Emin Tufan Çetin [tr], Kukuh Syafaat [id],
|
||||
Aurimas Černius [lt]
|
||||
|
||||
40.alpha.1.1
|
||||
============
|
||||
* Adapt to settings moving to gsettings-desktop-schemas [Carlos; !1416]
|
||||
* Misc. bug fixes and cleanups [Georges; !1667]
|
||||
|
||||
Contributors:
|
||||
Carlos Garnacho, Georges Basile Stavracas Neto
|
||||
|
||||
40.alpha.1
|
||||
==========
|
||||
* Base ClutterEffects on ClutterPaintNodes [Georges; !1340, !1355]
|
||||
* xwayland: Set xrandr primary output [Aleksandr; !1558]
|
||||
* Add paint node based blur support [Georges; !1627, !1646]
|
||||
* Disable CRTCs if there is no monitor [Kai-Heng; !1561]
|
||||
* Fix updates of mipmapped animated backgrounds [Daniel; !1664]
|
||||
* Allow remote desktop clients to specify scroll source [Pascal; !1636]
|
||||
* Support the color transform matrix RandR property on X11 [Aaron; !1048]
|
||||
* Plugged memory leaks [Jonas D.; !1632]
|
||||
* Fixed crashes [Jonas Å., Olivier, Carlos; !1557, !1648, !1643, !1654, !1663]
|
||||
* Misc. bug fixes and cleanups [Olivier, Niels, Carlos, Jonas Å., Florian,
|
||||
Jonas D., Daniel, Georges, Michel, Sebastian, Marc-Antoine; !1621, !1622,
|
||||
!1624, !1623, !1625, !1626, !1630, !1631, !1576, !1635, !1640, !1642,
|
||||
!1639, !1644, !1637, !1615, !1647, !1633, !1634, !1651, !1652, !1657,
|
||||
!1660, !1658, !1665, !1649, !1668, !1655]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Michel Dänzer, Jonas Dreßler, Kai-Heng Feng, Olivier Fourdan,
|
||||
Carlos Garnacho, Niels De Graef, Sebastian Keller, Aleksandr Mezin,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack,
|
||||
Marc-Antoine Perennou, Aaron Plattner, Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Kjartan Maraas [nb], Juliano de Souza Camargo [pt], Florentina Mușat [ro],
|
||||
Daniel Mustieles [es], Jordi Mas i Hernandez [ca], Fabio Tomat [fur],
|
||||
Philipp Kiemle [de], Asier Sarasua Garmendia [eu], Aurimas Černius [lt],
|
||||
Fran Dieguez [gl], Hugo Carvalho [pt], Matej Urbančič [sl]
|
||||
|
||||
40.alpha
|
||||
========
|
||||
* Replace CoglMatrix with graphene_matrix [Georges; !1439]
|
||||
* Allow to specify debug topics in MUTTER_DEBUG [Jonas Å.; !1465]
|
||||
* Fix unwanted position changes on window resize
|
||||
[Jonas Å., Olivier, Robert; !1477, !1495]
|
||||
* Do not disable the X Security extension by default [Olivier; !1485]
|
||||
* Fix _NET_WM_FRAME_DRAWN timestamps [Jonas Å.; !1494]
|
||||
* Fix tiling to the correct monitor [Florian; #1389]
|
||||
* Only snap to window edges when CTRL is pressed [Florian; #679609]
|
||||
* Add support for scroll button locking [Peter; !1432]
|
||||
* Clip Frustra [Georges; !1489]
|
||||
* Improve tablet-mode-switch support [Hans; !1506]
|
||||
* Fix missed redraws of newly-mapped actors [Jonas D.; !1366, #1494]
|
||||
* Gracefully handle Xwayland crashes [Carlos; !1447]
|
||||
* wayland: Provide previous window dimensions on restore [Christian; !801]
|
||||
* Remove the ClutterActor::paint signal [Jonas; !1522]
|
||||
* Fix background artifacts in magnifier [Daniel; #1480]
|
||||
* Use raycasting for picking [Georges; !1509]
|
||||
* Fix monitor tiling support on X11 [Jonas Å.; #1524]
|
||||
* Fix xwayland grabs for override-redirect windows [Olivier; !1254]
|
||||
* Fix device configuration not being picked up on X11 [Carlos; !1553]
|
||||
* Support tagging devices as primary GPU via udev [Jonas Å.; !1562]
|
||||
* Fix size hints with CSD [Olivier; !1594]
|
||||
* Fix unresponsive input after screen blank [Simon; !1601]
|
||||
* Cull actors when picking [Georges; !1520]
|
||||
* Handle input in a thread [Carlos; !1403]
|
||||
* Improve freezes when switching workspace [Jonas Å.; !1616]
|
||||
* Plugged memory leaks [Ray; !1225]
|
||||
* Fixed crashes [Christian, Olivier, Daniel, Robert, Jonas Å., Florian Z.,
|
||||
Simon, Carlos; #1481, !1529, !1519, !1534, #1521, !1563, !1604, !1605,
|
||||
!1607, !1612]
|
||||
* Misc. bug fixes and cleanups [Florian, Carlos, Olivier, Georges, Björn,
|
||||
Jonas Å., Julius, Corentin, Bastien, Robert, Daniel, Niels, Jonas D., Uday,
|
||||
Ian, Jordan, Piotr; !1473, !1472, !1438, #1449, !1475, !1474, !1481, !1466,
|
||||
!1483, !1427, !1413, !1103, !1467, !1339, !1297, #1384, !1491, !528, !1496,
|
||||
!1510, !1507, !1387, !1498, !1515, !1516, !1517, !1486, !1524, !1527, !1528,
|
||||
!1531, !1532, !1521, !1535, #1490, !1545, !1555, !1564, !1549, !1567, !1565,
|
||||
!1572, !1569, !1573, !1566, !1525, !1468, !1578, !1583, !1584, !1585, !1571,
|
||||
!1327, !1586, !1590, !1588, !1050, !1596, !1592, !1587, !1599, !1577, !1511,
|
||||
!1591, !1603, !1611, !1593, !1617, !1619]
|
||||
|
||||
Contributors:
|
||||
Björn Daase, Jonas Dreßler, Piotr Drąg, Olivier Fourdan, Carlos Garnacho,
|
||||
Hans de Goede, Niels De Graef, Peter Hutterer, Julius Lehmann, Robert Mader,
|
||||
Simon McVittie, Florian Müllner, Georges Basile Stavracas Neto,
|
||||
Bastien Nocera, Corentin Noël, Jordan Petridis, Uday Kiran Pichika,
|
||||
Christian Rauch, Ian Douglas Scott, Ray Strode, Daniel van Vugt,
|
||||
Florian Zwoch, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Juliano de Souza Camargo [pt], Ask Hjorth Larsen [da], Yuri Chornoivan [uk]
|
||||
|
||||
3.38.1
|
||||
======
|
||||
* Fix Night Light updates after DPMS [Jonas, Benjamin; #1392]
|
||||
* Fix button scrolling on X11 [Peter; !1431]
|
||||
* Always use correct font-dpi setting on X11 [Marco; !1444]
|
||||
* Improve handling of scanout failures [Jonas; #1410]
|
||||
* Fix middle/right button mixup in scroll button assignment [Peter; !1433]
|
||||
* Fix resizing of attached modal dialogs on wayland [Jonas; !1446]
|
||||
* Enable KMS modifiers on devices that need them [Karol; !1443]
|
||||
* Fix IM handling on X11 [Carlos; #1413]
|
||||
* Fix glitches in "undefined" screencast areas [Jonas; !1459]
|
||||
* Fix visual glitches on background with fractional scaling [Daniel; !1464]
|
||||
* Fix using correct refresh rate [Jonas; #1430]
|
||||
* Misc. bug fixes and cleanups [Daniel, Carlos, Robert, Simon, Sergio; !1362,
|
||||
!1448, !1452, !1273, !1454, !1429, !1460, !1458, !1463, !1462]
|
||||
* Plugged memory leaks [Ray; !1449, !1451]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Benjamin Berg, Sergio Costas, Carlos Garnacho,
|
||||
Karol Herbst, Peter Hutterer, Robert Mader, Simon McVittie, Ray Strode,
|
||||
Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Juliano de Souza Camargo [pt], Rafael Fontenelle [pt_BR],
|
||||
Yosef Or Boczko [he], Jordi Mas [ca]
|
||||
|
||||
3.38.0
|
||||
======
|
||||
* screencast: Only use DMA buffers for i915 [Jonas; !1442]
|
||||
* Fixed crashes [Jonas, Simon; !1430, #1414]
|
||||
|
||||
Contributors:
|
||||
Simon McVittie, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Anders Jonsson [sv], Gil Forcada [ca], Balázs Meskó [hu], Tim Sabsch [de],
|
||||
Milo Casagrande [it], Bruce Cowan [en_GB], Rūdolfs Mazurs [lv]
|
||||
|
||||
3.37.92
|
||||
=======
|
||||
* Fix stale cursor positions in remote desktop sessions [Georges; !1417]
|
||||
* xwayland: Add a setting to disable selected X extensions [Olivier; !1405]
|
||||
* Fix screencasting when using QXL [Jonas Å., Grey; !1318]
|
||||
* Cull actors that don't intersect with the redraw clip [Daniel; !1359]
|
||||
* Optimize painting of backgrounds when culling is unavailable [Daniel; !1363]
|
||||
* Improve support for Hangul input method [Carlos; !1286]
|
||||
* Support debug paint overlay for opaque regions [Robert; !1372]
|
||||
* Fix launching flatpak applications when autostarting Xwayland [Carlos; !1424]
|
||||
* Add support for capture scanouts in screencasts [Georges; !1421]
|
||||
* Allow integrated tablet devices to cycle outputs [Carlos; !1201]
|
||||
* Improve mapping input devices to the most relevant output [Carlos; !1202]
|
||||
* Only enable auto-rotation in touch mode [Carlos; !1311]
|
||||
* Fixed crashes [Pascal, Robert, Carlos, Benjamin, Marco; !1414, !1409, !1408,
|
||||
!1415, #1395, !1392, !1371, #1345]
|
||||
* Misc. bug fixes and cleanups [Björn, Jonas D., Florian; !1410, !1358, !1425]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Benjamin Berg, Grey Christoforo, Björn Daase,
|
||||
Jonas Dreßler, Olivier Fourdan, Carlos Garnacho, Robert Mader,
|
||||
Florian Müllner, Georges Basile Stavracas Neto, Pascal Nowack,
|
||||
Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Marek Černocký [cs], Aurimas Černius [lt], Asier Sarasua Garmendia [eu],
|
||||
Gwan-gyeong Mun [ko], Yuri Chornoivan [uk], Boyuan Yang [zh_CN],
|
||||
Kukuh Syafaat [id], Piotr Drąg [pl], Rafael Fontenelle [pt_BR],
|
||||
Марко Костић [sr], Matej Urbančič [sl], Fabio Tomat [fur],
|
||||
Daniel Mustieles [es], Fran Dieguez [gl], Goran Vidović [hr],
|
||||
Claude Paroz [fr], Andre Klapper [or, ug, te], Emin Tufan Çetin [tr]
|
||||
|
||||
3.37.91
|
||||
=======
|
||||
* Fix initial state of display mode OSD [Jian-Hong; #1362]
|
||||
* Fixed crashes [Jonas Å., Robert; !1407, !1411]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Christian; !1404, !1364, #1331]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Robert Mader, Jian-Hong Pan, Christian Rauch
|
||||
|
||||
Translators:
|
||||
Fran Dieguez [gl], Daniel Mustieles [es], Florentina Mușat [ro],
|
||||
Kukuh Syafaat [id], Piotr Drąg [pl], Emin Tufan Çetin [tr], Марко Костић [sr],
|
||||
Akarshan Biswas [bn_IN], Matej Urbančič [sl], Boyuan Yang [zh_CN],
|
||||
Goran Vidović [hr], Rafael Fontenelle [pt_BR]
|
||||
|
||||
3.37.90
|
||||
=======
|
||||
* Fix using NEAREST filter for backgrounds on scaled monitors [Daniel V.; !1346]
|
||||
* Screencast fixes and improvements [Jonas; !1361, !1377, !1391]
|
||||
* Support tap-button-map and tap-drag-lock touchpad settings [Giusy; !1319]
|
||||
* Fix wine copy & paste [Sebastian; !1369]
|
||||
* Fix shadows of server-side decorated XWayland windows [Olivier; #1358]
|
||||
* Replace some loaded terms with more descriptive ones [Olivier; !1396]
|
||||
* Add API to launch trusted wayland clients [Sergio; #741]
|
||||
* Skip displays with 'non-desktop' property set [Philipp; !1393]
|
||||
* Invalidate offscreen effect cache on video memory purge [Daniel V.; !1374]
|
||||
* Add wl_shm support for 10 bpc and 16 bpc half float formats [Jonas; !804]
|
||||
* Fixed crashes [Jonas, Erik, Martin; !1365, !1375, #1343]
|
||||
* Misc. bug fixes and cleanups [Daniel V., Carlos, Olivier, Christian,
|
||||
Daniel * G., Jonas, Florian; !1370, !1376, !1385, !1352, !1386, !1390,
|
||||
!1388, !1397, !1398, !1401]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Sergio Costas, Olivier Fourdan, Carlos Garnacho,
|
||||
Christian Hergert, Sebastian Keller, Erik Kurzinger, Giusy Margarita,
|
||||
Daniel García Moreno, Florian Müllner, Daniel van Vugt, Martin Whitaker,
|
||||
Philipp Zabel
|
||||
|
||||
Translators:
|
||||
Fabio Tomat [fur], Rafael Fontenelle [pt_BR], Jordi Mas [ca],
|
||||
Yuri Chornoivan [uk], Alexandre Franke [fr]
|
||||
|
||||
3.37.3
|
||||
======
|
||||
* Support custom keyboard layouts in $XDG_CONFIG_HOME/xkb [Peter; !936]
|
||||
* Optimize resource scale computation [Jonas D.; !1196, !1276, !1343]
|
||||
* Allow animating ClutterActor's content property [Georges; !1301]
|
||||
* Implement backgrounds as ClutterContent [Georges; !1302]
|
||||
* Add ClutterAlignContraint:pivot-point property [Jonas D.; !737]
|
||||
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
|
||||
* Do not paint textures of fully obscured windows [Robert; !1326]
|
||||
* Use a more appropriate combine function on opaque areas [Daniel; !1331]
|
||||
* Fix remote desktop being broken without screencast session [Olivier; #1307]
|
||||
* Remove more long-deprecated Clutter APIs [Adam, Georges; !1194, !1332]
|
||||
* Drive each monitor by its own frame clock [Jonas Å.; !1285]
|
||||
* Fix copy/paste failures on X11 [Carlos; !1350]
|
||||
* Mipmap background texture rendering [Daniel; !1347]
|
||||
* Plugged memory leaks [Sebastian, Jonas D.; !1293, !1281, !1304]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Daniel, Corentin, Carlos,
|
||||
Sebastian, Michel, Robert, Florian; !1288, !1289, !1291, !1296, !1292, !1298,
|
||||
!1300, !1303, !1290, !1287, !1306, !1305, !1308, !1313, !1250, !1314, !1267,
|
||||
!1275, !1317, !1270, !1322, !1181, !1282, !1325, !1323, !1240, !1295, !1329,
|
||||
!1333, !1334, !1336, !1341, #1312, !1345, !1349, !1356, #873, !1310, !1357]
|
||||
|
||||
Contributors:
|
||||
Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho,
|
||||
Peter Hutterer, Adam Jackson, Sebastian Keller, Robert Mader, Florian Müllner,
|
||||
Georges Basile Stavracas Neto, Corentin Noël, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
3.37.2
|
||||
======
|
||||
* Fix move-to-center keybinding with multiple monitors [Sergey; #1073]
|
||||
@ -994,7 +503,7 @@ Contributors:
|
||||
3.31.92
|
||||
=======
|
||||
* Fix flicker of apps that use multiple SHM buffers [Jonas Å.; #199]
|
||||
* Don't disable page flips after temporary failures [Jonas Å.; #460]
|
||||
* Don't disable page flips after temporary failues [Jonas Å.; #460]
|
||||
* Improve redraw performance [Carlos; !196]
|
||||
* Add cursor-mode support to window screencasting [Jonas Å.; !413]
|
||||
* Add back support for system-wide monitor configurations [Jonas Å.; !253]
|
||||
@ -1406,7 +915,7 @@ Translations:
|
||||
=======
|
||||
* Reduce memory use of suspended instances [Jonas; #786299]
|
||||
* Make supported scales determination saner [Rui; #786474]
|
||||
* Fix crash on inhibit-shortcuts dialog response [Jonas; #786385]
|
||||
* Fix crash on inhibit-shortcuts dialog reponse [Jonas; #786385]
|
||||
* Support libinput's tag-and-drag setting [freeroot; #775755]
|
||||
* Avoid overlapping keybindings with multiple layouts [Jonas; #786408]
|
||||
* Fix non-transformed cursor on rotated monitors [Jonas; #786023]
|
||||
@ -1725,7 +1234,7 @@ Translations:
|
||||
* Consider XDG_SESSION_TYPE when determining session type [Jouke; #759388]
|
||||
* Re-add support for edge scrolling on some touchpads [Bastien; #768245]
|
||||
* Support mouse and trackball acceleration profile [Jonas; #769179]
|
||||
* Draw monitor content to individual framebuffer [Jonas; #768976]
|
||||
* Draw monitor contentn to individual framebuffer [Jonas; #768976]
|
||||
* Support virtual input devices [Jonas, Carlos; #765009]
|
||||
* Set correct output scale on hotplug [Jonas; #769505]
|
||||
* Misc. bug fixes and cleanups [Florian, Jonas, Thomas, Bastien, Carlos;
|
||||
@ -2550,7 +2059,7 @@ Translations:
|
||||
* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399]
|
||||
* Don't save pixbuf data in user data [Tim; #706777]
|
||||
* Don't queue redraws for obscured regions [Adel; #703332]
|
||||
* Support the opaque region hints for wayland clients [Jasper; #707019]
|
||||
* Suppor the opaque region hints for wayland clients [Jasper; #707019]
|
||||
* Turn blending off when drawing entirely opaque regions [Jasper; #707019]
|
||||
* Check event timestamps before reconfiguring [Giovanni; #706735]
|
||||
* Merge the DBus API for display configuration in the wayland branch [Giovanni]
|
||||
@ -3035,7 +2544,7 @@ Translations:
|
||||
======
|
||||
* Automaximize large windows on map [Adel; #671677]
|
||||
* When unmaximizing windows, make sure the unminimized size
|
||||
is significantly less than the maximized size [Adel; #671677]
|
||||
is signficantly less than the maximized size [Adel; #671677]
|
||||
* Don't offer maximize option for windows larger than the screen
|
||||
[Jasper; #643606]
|
||||
* Always focus the window immediately underneath without restacking
|
||||
@ -3135,7 +2644,7 @@ Translations:
|
||||
* Move from GConf to GSettings for preferences [Florian; #635378]
|
||||
* Add meta_display_add_keybinding()/meta_display_remove_keybinding()
|
||||
to allow creating new keybindings at runtime [Florian; #663428]
|
||||
* Add support for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE
|
||||
* Add suport for new _NET_WM_STATE_FOCUSED atom in _NET_WM_STATE
|
||||
to allow applications to draw unfocused windows differently
|
||||
[Rui; #661427]
|
||||
* Add meta_window_move_resize_frame() to allow specifying the
|
||||
@ -3247,7 +2756,7 @@ Contributors:
|
||||
for easy resizing with thin borders. (New draggable_border_width GConf key
|
||||
controls the total width of visible and invisible borders.)
|
||||
[Jasper; #644930]
|
||||
* Draw rounded window corners with antialiasing [Jasper; #628195]
|
||||
* Draw rounded window corners with antialising [Jasper; #628195]
|
||||
* Unredirect override-redirect fullscreen windows, such as full-screen
|
||||
3D games to avoid any performance impact [Adel; #597014]
|
||||
* Add :resizable and :above properties to MetaWindow. [Tim; #653858]
|
||||
@ -3340,7 +2849,7 @@ Translations:
|
||||
3.0.2.1
|
||||
=======
|
||||
* When saving the session, use the "program name" rather than
|
||||
hardcoding mutter, fixing session saving for gnome-shell [Matthias]
|
||||
harcoding mutter, fixing session saving for gnome-shell [Matthias]
|
||||
https://bugzilla.gnome.org/show_bug.cgi?id=648828
|
||||
|
||||
Contributors:
|
||||
@ -3658,7 +3167,7 @@ Bugs fixed:
|
||||
634779 MetaWindowGroup: further optimize paints by using current scissor
|
||||
634833 Draw the root window background
|
||||
592382 improve shadow effect
|
||||
628199 Add antialiasing to arc and line drawing operations
|
||||
628199 Add antialising to arc and line drawing operations
|
||||
633002 meta-actor-window: Use G_UNLIKELY for TFP check
|
||||
634771 MetaStackTracker: Avoid queueing resync for obvious no-ops
|
||||
635421 Fix crash in check_needs_shadow
|
||||
@ -3855,7 +3364,7 @@ Fixed Bugs:
|
||||
- Allow a theme to turn on title ellipsization
|
||||
* Performance enhancements:
|
||||
- Stream raw damage updates to ClutterX11TexturePixmap
|
||||
to enable partial stage updates when windows change [Robert]
|
||||
to enable partial stage updates when windos change [Robert]
|
||||
- Don't trap XErrors in meta_compositor_process_event [Adel]
|
||||
* Add meta_prefs_override_preference_location(); this allows
|
||||
a plugin like GNOME Shell to redirect preferences to a
|
||||
@ -3900,7 +3409,7 @@ Fixed Bugs:
|
||||
613136 - remove over-restrictive assert from meta_prefs_get_workspace_name()
|
||||
613398 - Don't trap XErrors in meta_compositor_process_event
|
||||
615586 - Allow redirecting preferences to a different GConf key
|
||||
615672 - can't compile mutter error: dereferencing pointer ‘p’ does break
|
||||
615672 - cant' compile mutter error: dereferencing pointer ‘p’ does break
|
||||
strict-aliasing rules
|
||||
616050 - alt-tab infrastructure patches
|
||||
616274 - mutter from git fails with gcc 4.5 (on new warning)
|
||||
@ -4846,7 +4355,7 @@ Arthur Taylor, Elijah Newren, Josselin Mouette, Havoc Pennington,
|
||||
Benjamin Berg, and Carlo Wood for improvements in this release.
|
||||
|
||||
- new icon for the force-quit dialog (Jaap) [#396655]
|
||||
- add configurable mouse click action abilities, and clean up lots of
|
||||
- add configureable mouse click action abilities, and clean up lots of
|
||||
related code (Linus) [#408899, #408902, others]
|
||||
- add schemeas for middle and right click titlebar actions (Charlie)
|
||||
[#408903]
|
||||
@ -5400,7 +4909,7 @@ this release.
|
||||
running with --disable-gconf. Make --disable-gconf actually work.
|
||||
(Elijah) [#326661]
|
||||
- fix some reading-from-free'd-data errors (Søren) [#327575]
|
||||
- fix an uninitialized value problem when in raise-on-click mode
|
||||
- fix an unitialized value problem when in raise-on-click mode
|
||||
(Søren) [#327572]
|
||||
- avoid flashing original-sized window when closing a maximized
|
||||
window (Elijah) [#317254]
|
||||
|
31
README.md
31
README.md
@ -26,34 +26,15 @@ debugging purposes.
|
||||
|
||||
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter.
|
||||
|
||||
It can be useful to look at the documentation available at the
|
||||
[Wiki](https://gitlab.gnome.org/GNOME/mutter/-/wikis/home).
|
||||
|
||||
## Coding style and conventions
|
||||
|
||||
See [HACKING.md](./HACKING.md).
|
||||
|
||||
## Git messages
|
||||
The coding style used is primarily the GNU flavor of the [GNOME coding
|
||||
style](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en)
|
||||
with some minor additions such as preferring `stdint.h` types over GLib
|
||||
fundamental types, and a soft 80 character line limit. However, in general,
|
||||
look at the file you're editing for inspiration.
|
||||
|
||||
Commit messages should follow the [GNOME commit message
|
||||
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
|
||||
to either an issue or a merge request in each commit. Try to always prefix
|
||||
commit subjects with a relevant topic, such as `compositor:` or
|
||||
`clutter/actor:`, and it's always better to write too much in the commit
|
||||
message body than too little.
|
||||
|
||||
## Default branch
|
||||
|
||||
The default development branch is `main`. If you still have a local
|
||||
checkout under the old name, use:
|
||||
```sh
|
||||
git checkout master
|
||||
git branch -m master main
|
||||
git fetch
|
||||
git branch --unset-upstream
|
||||
git branch -u origin/main
|
||||
git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main
|
||||
```
|
||||
to either an issue or a merge request in each commit.
|
||||
|
||||
## License
|
||||
|
||||
|
138
check-style.py
138
check-style.py
@ -1,138 +0,0 @@
|
||||
#!/bin/env python3
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# Path relative to this script
|
||||
uncrustify_cfg = 'tools/uncrustify.cfg'
|
||||
|
||||
def run_diff(sha):
|
||||
proc = subprocess.Popen(["git", "diff", "-U0", "--function-context", sha, "HEAD"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
files = proc.stdout.read().strip().decode('utf-8')
|
||||
return files.split('\n')
|
||||
|
||||
def find_chunks(diff):
|
||||
file_entry_re = re.compile('^\+\+\+ b/(.*)$')
|
||||
diff_chunk_re = re.compile('^@@ -\d+,\d+ \+(\d+),(\d+)')
|
||||
file = None
|
||||
chunks = []
|
||||
|
||||
for line in diff:
|
||||
match = file_entry_re.match(line)
|
||||
if match:
|
||||
file = match.group(1)
|
||||
|
||||
match = diff_chunk_re.match(line)
|
||||
if match:
|
||||
start = int(match.group(1))
|
||||
len = int(match.group(2))
|
||||
end = start + len
|
||||
|
||||
if len > 0 and (file.endswith('.c') or file.endswith('.h') or file.endswith('.vala')):
|
||||
chunks.append({ 'file': file, 'start': start, 'end': end })
|
||||
|
||||
return chunks
|
||||
|
||||
def reformat_chunks(chunks, rewrite):
|
||||
# Creates temp file with INDENT-ON/OFF comments
|
||||
def create_temp_file(file, start, end):
|
||||
with open(file) as f:
|
||||
tmp = tempfile.NamedTemporaryFile()
|
||||
tmp.write(b'/** *INDENT-OFF* **/\n')
|
||||
for i, line in enumerate(f):
|
||||
if i == start - 2:
|
||||
tmp.write(b'/** *INDENT-ON* **/\n')
|
||||
|
||||
tmp.write(bytes(line, 'utf-8'))
|
||||
|
||||
if i == end - 2:
|
||||
tmp.write(b'/** *INDENT-OFF* **/\n')
|
||||
|
||||
tmp.seek(0)
|
||||
|
||||
return tmp
|
||||
|
||||
# Removes uncrustify INDENT-ON/OFF helper comments
|
||||
def remove_indent_comments(output):
|
||||
tmp = tempfile.NamedTemporaryFile()
|
||||
|
||||
for line in output:
|
||||
if line != b'/** *INDENT-OFF* **/\n' and line != b'/** *INDENT-ON* **/\n':
|
||||
tmp.write(line)
|
||||
|
||||
tmp.seek(0)
|
||||
|
||||
return tmp
|
||||
|
||||
changed = None
|
||||
|
||||
for chunk in chunks:
|
||||
# Add INDENT-ON/OFF comments
|
||||
tmp = create_temp_file(chunk['file'], chunk['start'], chunk['end'])
|
||||
|
||||
# uncrustify chunk
|
||||
proc = subprocess.Popen(["uncrustify", "-c", uncrustify_cfg, "-f", tmp.name], stdout=subprocess.PIPE)
|
||||
reindented = proc.stdout.readlines()
|
||||
proc.wait()
|
||||
if proc.returncode != 0:
|
||||
continue
|
||||
|
||||
tmp.close()
|
||||
|
||||
# Remove INDENT-ON/OFF comments
|
||||
formatted = remove_indent_comments(reindented)
|
||||
|
||||
if dry_run is True:
|
||||
# Show changes
|
||||
proc = subprocess.Popen(["diff", "-up", "--color=always", chunk['file'], formatted.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
diff = proc.stdout.read().decode('utf-8')
|
||||
if diff != '':
|
||||
output = re.sub('\t', '↦\t', diff)
|
||||
print(output)
|
||||
changed = True
|
||||
else:
|
||||
# Apply changes
|
||||
diff = subprocess.Popen(["diff", "-up", chunk['file'], formatted.name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
patch = subprocess.Popen(["patch", chunk['file']], stdin=diff.stdout)
|
||||
diff.stdout.close()
|
||||
patch.communicate()
|
||||
|
||||
formatted.close()
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='Check code style.')
|
||||
parser.add_argument('--sha', metavar='SHA', type=str,
|
||||
help='SHA for the commit to compare HEAD with')
|
||||
parser.add_argument('--dry-run', '-d', type=bool,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help='Only print changes to stdout, do not change code')
|
||||
parser.add_argument('--rewrite', '-r', type=bool,
|
||||
action=argparse.BooleanOptionalAction,
|
||||
help='Whether to amend the result to the last commit (e.g. \'git rebase --exec "%(prog)s -r"\')')
|
||||
|
||||
# Change CWD to script location, necessary for always locating the configuration file
|
||||
os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
|
||||
|
||||
args = parser.parse_args()
|
||||
sha = args.sha or 'HEAD^'
|
||||
rewrite = args.rewrite
|
||||
dry_run = args.dry_run
|
||||
|
||||
diff = run_diff(sha)
|
||||
chunks = find_chunks(diff)
|
||||
changed = reformat_chunks(chunks, rewrite)
|
||||
|
||||
if dry_run is not True and rewrite is True:
|
||||
proc = subprocess.Popen(["git", "commit", "--all", "--amend", "-C", "HEAD"], stdout=subprocess.DEVNULL)
|
||||
os._exit(0)
|
||||
elif dry_run is True and changed is True:
|
||||
print ("\nIssue the following command in your local tree to apply the suggested changes (needs uncrustify installed):\n\n $ git rebase origin/main --exec \"./check-style.py -r\" \n")
|
||||
os._exit(-1)
|
||||
|
||||
os._exit(0)
|
@ -28,7 +28,7 @@
|
||||
#include "cally-actor.h"
|
||||
|
||||
/*
|
||||
* Auxiliary define, in order to get the clutter actor from the AtkObject using
|
||||
* Auxiliar define, in order to get the clutter actor from the AtkObject using
|
||||
* AtkGObject methods
|
||||
*
|
||||
*/
|
||||
|
@ -72,7 +72,9 @@
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "clutter/clutter-actor-private.h"
|
||||
#ifdef CLUTTER_WINDOWING_X11
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@ -765,11 +767,10 @@ static gboolean
|
||||
cally_actor_action_do_action (AtkAction *action,
|
||||
gint index)
|
||||
{
|
||||
CallyActor *cally_actor = NULL;
|
||||
AtkStateSet *set = NULL;
|
||||
CallyActorPrivate *priv = NULL;
|
||||
CallyActorActionInfo *info = NULL;
|
||||
gboolean did_action = FALSE;
|
||||
CallyActor *cally_actor = NULL;
|
||||
AtkStateSet *set = NULL;
|
||||
CallyActorPrivate *priv = NULL;
|
||||
CallyActorActionInfo *info = NULL;
|
||||
|
||||
cally_actor = CALLY_ACTOR (action);
|
||||
priv = cally_actor->priv;
|
||||
@ -777,19 +778,21 @@ cally_actor_action_do_action (AtkAction *action,
|
||||
set = atk_object_ref_state_set (ATK_OBJECT (cally_actor));
|
||||
|
||||
if (atk_state_set_contains_state (set, ATK_STATE_DEFUNCT))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!atk_state_set_contains_state (set, ATK_STATE_SENSITIVE) ||
|
||||
!atk_state_set_contains_state (set, ATK_STATE_SHOWING))
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
g_object_unref (set);
|
||||
|
||||
info = _cally_actor_get_action_info (cally_actor, index);
|
||||
|
||||
if (info == NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (info->do_action_func == NULL)
|
||||
goto out;
|
||||
return FALSE;
|
||||
|
||||
if (!priv->action_queue)
|
||||
priv->action_queue = g_queue_new ();
|
||||
@ -799,12 +802,7 @@ cally_actor_action_do_action (AtkAction *action,
|
||||
if (!priv->action_idle_handler)
|
||||
priv->action_idle_handler = g_idle_add (idle_do_action, cally_actor);
|
||||
|
||||
did_action = TRUE;
|
||||
|
||||
out:
|
||||
g_clear_object (&set);
|
||||
|
||||
return did_action;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -970,7 +968,7 @@ cally_actor_real_notify_clutter (GObject *obj,
|
||||
* paint it; we don't want this to generate an ATK
|
||||
* state change
|
||||
*/
|
||||
if (clutter_actor_is_painting_unmapped (actor))
|
||||
if (clutter_actor_is_in_clone_paint (actor))
|
||||
return;
|
||||
|
||||
state = ATK_STATE_SHOWING;
|
||||
@ -1086,7 +1084,7 @@ cally_actor_add_action_full (CallyActor *cally_actor,
|
||||
|
||||
priv = cally_actor->priv;
|
||||
|
||||
info = g_new0 (CallyActorActionInfo, 1);
|
||||
info = g_slice_new (CallyActorActionInfo);
|
||||
info->name = g_strdup (action_name);
|
||||
info->description = g_strdup (action_description);
|
||||
info->keybinding = g_strdup (action_keybinding);
|
||||
@ -1106,7 +1104,7 @@ cally_actor_add_action_full (CallyActor *cally_actor,
|
||||
*
|
||||
* Removes a action, using the @action_id returned by cally_actor_add_action()
|
||||
*
|
||||
* Return value: %TRUE if the operation was successful, %FALSE otherwise
|
||||
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
@ -1140,7 +1138,7 @@ cally_actor_remove_action (CallyActor *cally_actor,
|
||||
* Removes an action, using the @action_name used when the action was added
|
||||
* with cally_actor_add_action()
|
||||
*
|
||||
* Return value: %TRUE if the operation was successful, %FALSE otherwise
|
||||
* Return value: %TRUE if the operation was succesful, %FALSE otherwise
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
@ -1191,5 +1189,5 @@ _cally_actor_destroy_action_info (gpointer action_info,
|
||||
if (info->notify)
|
||||
info->notify (info->user_data);
|
||||
|
||||
g_free (info);
|
||||
g_slice_free (CallyActorActionInfo, info);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ static AtkStateSet* cally_stage_ref_state_set (AtkObject *obj);
|
||||
/* AtkWindow */
|
||||
static void cally_stage_window_interface_init (AtkWindowIface *iface);
|
||||
|
||||
/* Auxiliary */
|
||||
/* Auxiliar */
|
||||
static void cally_stage_activate_cb (ClutterStage *stage,
|
||||
gpointer data);
|
||||
static void cally_stage_deactivate_cb (ClutterStage *stage,
|
||||
@ -134,11 +134,8 @@ cally_stage_notify_key_focus_cb (ClutterStage *stage,
|
||||
|
||||
if (self->priv->key_focus != NULL)
|
||||
{
|
||||
if (self->priv->key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
}
|
||||
g_object_remove_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
old = clutter_actor_get_accessible (self->priv->key_focus);
|
||||
}
|
||||
else
|
||||
@ -163,11 +160,8 @@ cally_stage_notify_key_focus_cb (ClutterStage *stage,
|
||||
*
|
||||
* we remove the weak pointer above.
|
||||
*/
|
||||
if (key_focus != CLUTTER_ACTOR (stage))
|
||||
{
|
||||
g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
}
|
||||
g_object_add_weak_pointer (G_OBJECT (self->priv->key_focus),
|
||||
(gpointer *) &self->priv->key_focus);
|
||||
|
||||
new = clutter_actor_get_accessible (key_focus);
|
||||
}
|
||||
@ -228,7 +222,7 @@ cally_stage_window_interface_init (AtkWindowIface *iface)
|
||||
/* At this moment AtkWindow is just about signals */
|
||||
}
|
||||
|
||||
/* Auxiliary */
|
||||
/* Auxiliar */
|
||||
static void
|
||||
cally_stage_activate_cb (ClutterStage *stage,
|
||||
gpointer data)
|
||||
|
@ -1513,7 +1513,7 @@ cally_text_get_offset_at_point (AtkText *text,
|
||||
}
|
||||
|
||||
|
||||
/******** Auxiliary private methods ******/
|
||||
/******** Auxiliar private methods ******/
|
||||
|
||||
/* ClutterText only maintains the current cursor position and a extra selection
|
||||
bound, but this could be before or after the cursor. This method returns
|
||||
@ -1552,7 +1552,7 @@ _cally_text_delete_text_cb (ClutterText *clutter_text,
|
||||
|
||||
g_return_if_fail (CALLY_IS_TEXT (data));
|
||||
|
||||
/* Ignore zero length deletions */
|
||||
/* Ignore zero lengh deletions */
|
||||
if (end_pos - start_pos == 0)
|
||||
return;
|
||||
|
||||
@ -1653,7 +1653,7 @@ cally_text_insert_text (AtkEditableText *text,
|
||||
clutter_text_insert_text (CLUTTER_TEXT (actor),
|
||||
string, *position);
|
||||
|
||||
/* we suppose that the text insertion will be successful,
|
||||
/* we suppose that the text insertion will be succesful,
|
||||
clutter-text doesn't warn about it. A option would be search for
|
||||
the text, but it seems not really required */
|
||||
*position += length;
|
||||
@ -1866,7 +1866,7 @@ static gint
|
||||
_cally_atk_attribute_lookup_func (gconstpointer data,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
AtkTextAttribute attr = (AtkTextAttribute) GPOINTER_TO_INT (user_data);
|
||||
AtkTextAttribute attr = (AtkTextAttribute) user_data;
|
||||
AtkAttribute *at = (AtkAttribute *) data;
|
||||
if (!g_strcmp0 (at->name, atk_text_attribute_get_name (attr)))
|
||||
return 0;
|
||||
|
@ -54,7 +54,7 @@ clutter_actor_box_new (gfloat x_1,
|
||||
ClutterActorBox *
|
||||
clutter_actor_box_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterActorBox, 1);
|
||||
return g_slice_new0 (ClutterActorBox);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,7 +130,7 @@ ClutterActorBox *
|
||||
clutter_actor_box_copy (const ClutterActorBox *box)
|
||||
{
|
||||
if (G_LIKELY (box != NULL))
|
||||
return g_memdup2 (box, sizeof (ClutterActorBox));
|
||||
return g_slice_dup (ClutterActorBox, box);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -148,7 +148,7 @@ void
|
||||
clutter_actor_box_free (ClutterActorBox *box)
|
||||
{
|
||||
if (G_LIKELY (box != NULL))
|
||||
g_free (box);
|
||||
g_slice_free (ClutterActorBox, box);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -320,7 +320,7 @@ clutter_actor_box_get_area (const ClutterActorBox *box)
|
||||
* @y: Y coordinate of the point
|
||||
*
|
||||
* Checks whether a point with @x, @y coordinates is contained
|
||||
* within @box
|
||||
* withing @box
|
||||
*
|
||||
* Return value: %TRUE if the point is contained by the #ClutterActorBox
|
||||
*
|
||||
@ -554,7 +554,7 @@ _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
|
||||
*
|
||||
* The reason this is important is because effects will use this
|
||||
* API to determine the size of offscreen framebuffers and so for
|
||||
* a fixed-size object that may be animated across the screen we
|
||||
* a fixed-size object that may be animated accross the screen we
|
||||
* want to make sure that the stage paint-box has an equally stable
|
||||
* size so that effects aren't made to continuously re-allocate
|
||||
* a corresponding fbo.
|
||||
@ -583,7 +583,7 @@ _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
|
||||
|
||||
/* Now we redefine the top-left relative to the bottom right based on the
|
||||
* rounded width/height determined above + a constant so that the overall
|
||||
* size of the box will be stable and not dependent on the box's
|
||||
* size of the box will be stable and not dependant on the box's
|
||||
* position.
|
||||
*
|
||||
* Adding 3px to the width/height will ensure we cover the maximum of
|
||||
|
@ -26,6 +26,23 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/*< private >
|
||||
* ClutterRedrawFlags:
|
||||
* @CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION: Tells clutter the maximum
|
||||
* extents of what needs to be redrawn lies within the actors
|
||||
* current allocation. (Only use this for 2D actors though because
|
||||
* any actor with depth may be projected outside of its allocation)
|
||||
*
|
||||
* Flags passed to the clutter_actor_queue_redraw_with_clip ()
|
||||
* function
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_REDRAW_CLIPPED_TO_ALLOCATION = 1 << 0
|
||||
} ClutterRedrawFlags;
|
||||
|
||||
/*< private >
|
||||
* ClutterActorTraverseFlags:
|
||||
* CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST: Traverse the graph in
|
||||
@ -163,10 +180,10 @@ struct _ClutterTransformInfo
|
||||
graphene_point_t pivot;
|
||||
gfloat pivot_z;
|
||||
|
||||
graphene_matrix_t transform;
|
||||
CoglMatrix transform;
|
||||
guint transform_set : 1;
|
||||
|
||||
graphene_matrix_t child_transform;
|
||||
CoglMatrix child_transform;
|
||||
guint child_transform_set : 1;
|
||||
};
|
||||
|
||||
@ -203,11 +220,11 @@ void _clutter_actor_traverse
|
||||
gpointer user_data);
|
||||
ClutterActor * _clutter_actor_get_stage_internal (ClutterActor *actor);
|
||||
|
||||
void _clutter_actor_apply_modelview_transform (ClutterActor *self,
|
||||
graphene_matrix_t *matrix);
|
||||
void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
|
||||
ClutterActor *ancestor,
|
||||
graphene_matrix_t *matrix);
|
||||
void _clutter_actor_apply_modelview_transform (ClutterActor *self,
|
||||
CoglMatrix *matrix);
|
||||
void _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
|
||||
ClutterActor *ancestor,
|
||||
CoglMatrix *matrix);
|
||||
|
||||
void _clutter_actor_rerealize (ClutterActor *self,
|
||||
ClutterCallback callback,
|
||||
@ -228,21 +245,30 @@ void _clutter_actor_set_has_pointer
|
||||
void _clutter_actor_set_has_key_focus (ClutterActor *self,
|
||||
gboolean has_key_focus);
|
||||
|
||||
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
ClutterRedrawFlags flags,
|
||||
const ClutterPaintVolume *clip_volume);
|
||||
void _clutter_actor_queue_redraw_full (ClutterActor *self,
|
||||
ClutterRedrawFlags flags,
|
||||
const ClutterPaintVolume *volume,
|
||||
ClutterEffect *effect);
|
||||
|
||||
void _clutter_actor_finish_queue_redraw (ClutterActor *self);
|
||||
void _clutter_actor_finish_queue_redraw (ClutterActor *self,
|
||||
ClutterPaintVolume *clip);
|
||||
|
||||
gboolean _clutter_actor_set_default_paint_volume (ClutterActor *self,
|
||||
GType check_gtype,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
const char * _clutter_actor_get_debug_name (ClutterActor *self);
|
||||
const gchar * _clutter_actor_get_debug_name (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_push_clone_paint (void);
|
||||
void _clutter_actor_pop_clone_paint (void);
|
||||
|
||||
void _clutter_actor_shader_pre_paint (ClutterActor *actor,
|
||||
gboolean repeat);
|
||||
void _clutter_actor_shader_post_paint (ClutterActor *actor);
|
||||
|
||||
ClutterActorAlign _clutter_actor_get_effective_x_align (ClutterActor *self);
|
||||
|
||||
void _clutter_actor_handle_event (ClutterActor *actor,
|
||||
@ -252,6 +278,8 @@ void _clutter_actor_attach_clone
|
||||
ClutterActor *clone);
|
||||
void _clutter_actor_detach_clone (ClutterActor *actor,
|
||||
ClutterActor *clone);
|
||||
void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
|
||||
void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
|
||||
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
|
||||
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
|
||||
|
||||
@ -260,17 +288,11 @@ float clutter_actor_get_real_resource_scale
|
||||
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
|
||||
CoglTexture *texture);
|
||||
|
||||
void clutter_actor_finish_layout (ClutterActor *self,
|
||||
int phase);
|
||||
void clutter_actor_update_stage_views (ClutterActor *self,
|
||||
int phase);
|
||||
|
||||
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
|
||||
|
||||
gboolean clutter_actor_is_painting_unmapped (ClutterActor *self);
|
||||
|
||||
gboolean clutter_actor_get_redraw_clip (ClutterActor *self,
|
||||
ClutterPaintVolume *dst_old_pv,
|
||||
ClutterPaintVolume *dst_new_pv);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -187,6 +187,7 @@ struct _ClutterActor
|
||||
* chain up to the parent's implementation
|
||||
* @pick: virtual function, used to draw an outline of the actor with
|
||||
* the given color
|
||||
* @queue_redraw: class handler for #ClutterActor::queue-redraw
|
||||
* @event: class handler for #ClutterActor::event
|
||||
* @button_press_event: class handler for #ClutterActor::button-press-event
|
||||
* @button_release_event: class handler for
|
||||
@ -238,6 +239,10 @@ struct _ClutterActorClass
|
||||
void (* pick) (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context);
|
||||
|
||||
gboolean (* queue_redraw) (ClutterActor *actor,
|
||||
ClutterActor *leaf_that_queued,
|
||||
ClutterPaintVolume *paint_volume);
|
||||
|
||||
/* size negotiation */
|
||||
void (* get_preferred_width) (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@ -252,7 +257,7 @@ struct _ClutterActorClass
|
||||
|
||||
/* transformations */
|
||||
void (* apply_transform) (ClutterActor *actor,
|
||||
graphene_matrix_t *matrix);
|
||||
ClutterMatrix *matrix);
|
||||
|
||||
/* event signals */
|
||||
gboolean (* event) (ClutterActor *actor,
|
||||
@ -414,9 +419,7 @@ 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);
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_available_size (ClutterActor *self,
|
||||
gfloat x,
|
||||
@ -451,10 +454,6 @@ void clutter_actor_set_position
|
||||
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);
|
||||
@ -586,8 +585,7 @@ void clutter_actor_set_offscreen_redirect
|
||||
CLUTTER_EXPORT
|
||||
ClutterOffscreenRedirect clutter_actor_get_offscreen_redirect (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_should_pick (ClutterActor *self,
|
||||
ClutterPickContext *pick_context);
|
||||
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_in_clone_paint (ClutterActor *self);
|
||||
CLUTTER_EXPORT
|
||||
@ -799,21 +797,16 @@ void clutter_actor_get_translation
|
||||
gfloat *translate_z);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_transform (ClutterActor *self,
|
||||
const graphene_matrix_t *transform);
|
||||
const ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transform (ClutterActor *self,
|
||||
graphene_matrix_t *transform);
|
||||
ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_set_child_transform (ClutterActor *self,
|
||||
const graphene_matrix_t *transform);
|
||||
const ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_child_transform (ClutterActor *self,
|
||||
graphene_matrix_t *transform);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transformed_extents (ClutterActor *self,
|
||||
graphene_rect_t *rect);
|
||||
|
||||
ClutterMatrix *transform);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_transformed_position (ClutterActor *self,
|
||||
gfloat *x,
|
||||
@ -932,7 +925,7 @@ CLUTTER_EXPORT
|
||||
void clutter_actor_invalidate_transform (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_invalidate_paint_volume (ClutterActor *self);
|
||||
ClutterFrameClock * clutter_actor_pick_frame_clock (ClutterActor *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -83,6 +83,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterZoomAction, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorBox, clutter_actor_box_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColor, clutter_color_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMargin, clutter_margin_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMatrix, clutter_matrix_free)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintContext, clutter_paint_context_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintNode, clutter_paint_node_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintVolume, clutter_paint_volume_free)
|
||||
|
@ -73,6 +73,7 @@ struct _ClutterBackendClass
|
||||
ClutterStageWindow * (* create_stage) (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error);
|
||||
void (* init_events) (ClutterBackend *backend);
|
||||
void (* init_features) (ClutterBackend *backend);
|
||||
void (* add_options) (ClutterBackend *backend,
|
||||
GOptionGroup *group);
|
||||
@ -92,8 +93,6 @@ struct _ClutterBackendClass
|
||||
|
||||
ClutterSeat * (* get_default_seat) (ClutterBackend *backend);
|
||||
|
||||
gboolean (* is_display_server) (ClutterBackend *backend);
|
||||
|
||||
/* signals */
|
||||
void (* resolution_changed) (ClutterBackend *backend);
|
||||
void (* font_changed) (ClutterBackend *backend);
|
||||
@ -115,6 +114,12 @@ gboolean _clutter_backend_pre_parse (Clutter
|
||||
gboolean _clutter_backend_post_parse (ClutterBackend *backend,
|
||||
GError **error);
|
||||
|
||||
void _clutter_backend_init_events (ClutterBackend *backend);
|
||||
void _clutter_backend_copy_event_data (ClutterBackend *backend,
|
||||
const ClutterEvent *src,
|
||||
ClutterEvent *dest);
|
||||
void _clutter_backend_free_event_data (ClutterBackend *backend,
|
||||
ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_backend_translate_event (ClutterBackend *backend,
|
||||
gpointer native,
|
||||
@ -137,11 +142,6 @@ void clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
|
||||
|
||||
float clutter_backend_get_fallback_resource_scale (ClutterBackend *backend);
|
||||
|
||||
gboolean clutter_backend_is_display_server (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_backend_destroy (ClutterBackend *backend);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-event-private.h"
|
||||
@ -50,8 +52,25 @@
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-stage-window.h"
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
#include "wayland/clutter-wayland-compositor.h"
|
||||
#endif
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#ifdef CLUTTER_INPUT_X11
|
||||
#include "x11/clutter-backend-x11.h"
|
||||
#endif
|
||||
#ifdef CLUTTER_WINDOWING_EGL
|
||||
#include "egl/clutter-backend-eglnative.h"
|
||||
#endif
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <wayland-server.h>
|
||||
#include "wayland/clutter-wayland-compositor.h"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_FONT_NAME "Sans 10"
|
||||
|
||||
enum
|
||||
@ -67,6 +86,12 @@ G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT)
|
||||
|
||||
static guint backend_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
/* Global for being able to specify a compositor side wayland display
|
||||
* pointer before clutter initialization */
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
static struct wl_display *_wayland_compositor_display;
|
||||
#endif
|
||||
|
||||
static void
|
||||
clutter_backend_dispose (GObject *gobject)
|
||||
{
|
||||
@ -75,20 +100,28 @@ clutter_backend_dispose (GObject *gobject)
|
||||
/* clear the events still in the queue of the main context */
|
||||
_clutter_clear_events_queue ();
|
||||
|
||||
g_clear_object (&backend->dummy_onscreen);
|
||||
g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref);
|
||||
if (backend->stage_window)
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (backend->stage_window),
|
||||
(gpointer *) &backend->stage_window);
|
||||
backend->stage_window = NULL;
|
||||
}
|
||||
|
||||
g_clear_pointer (&backend->cogl_source, g_source_destroy);
|
||||
g_clear_pointer (&backend->font_name, g_free);
|
||||
g_clear_pointer (&backend->font_options, cairo_font_options_destroy);
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
||||
|
||||
g_source_destroy (backend->cogl_source);
|
||||
|
||||
g_free (backend->font_name);
|
||||
clutter_backend_set_font_options (backend, NULL);
|
||||
g_clear_object (&backend->input_method);
|
||||
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static gfloat
|
||||
@ -189,20 +222,22 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
CoglSwapChain *swap_chain;
|
||||
GError *internal_error;
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
|
||||
swap_chain = NULL;
|
||||
internal_error = NULL;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl renderer");
|
||||
backend->cogl_renderer = klass->get_renderer (backend, error);
|
||||
backend->cogl_renderer = klass->get_renderer (backend, &internal_error);
|
||||
|
||||
if (backend->cogl_renderer == NULL)
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Connecting the renderer");
|
||||
cogl_renderer_set_driver (backend->cogl_renderer, driver_id);
|
||||
if (!cogl_renderer_connect (backend->cogl_renderer, error))
|
||||
if (!cogl_renderer_connect (backend->cogl_renderer, &internal_error))
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating Cogl swap chain");
|
||||
@ -214,7 +249,7 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
backend->cogl_display = klass->get_display (backend,
|
||||
backend->cogl_renderer,
|
||||
swap_chain,
|
||||
error);
|
||||
&internal_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -230,7 +265,7 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
*/
|
||||
res = cogl_renderer_check_onscreen_template (backend->cogl_renderer,
|
||||
tmpl,
|
||||
error);
|
||||
&internal_error);
|
||||
|
||||
if (!res)
|
||||
goto error;
|
||||
@ -244,12 +279,17 @@ clutter_backend_do_real_create_context (ClutterBackend *backend,
|
||||
if (backend->cogl_display == NULL)
|
||||
goto error;
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
cogl_wayland_display_set_compositor_display (backend->cogl_display,
|
||||
_wayland_compositor_display);
|
||||
#endif
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Setting up the display");
|
||||
if (!cogl_display_setup (backend->cogl_display, error))
|
||||
if (!cogl_display_setup (backend->cogl_display, &internal_error))
|
||||
goto error;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Creating the Cogl context");
|
||||
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
|
||||
backend->cogl_context = cogl_context_new (backend->cogl_display, &internal_error);
|
||||
if (backend->cogl_context == NULL)
|
||||
goto error;
|
||||
|
||||
@ -382,6 +422,14 @@ clutter_backend_real_get_features (ClutterBackend *backend)
|
||||
flags |= CLUTTER_FEATURE_STAGE_STATIC;
|
||||
}
|
||||
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling");
|
||||
flags |= CLUTTER_FEATURE_SWAP_THROTTLE;
|
||||
}
|
||||
else
|
||||
CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling");
|
||||
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events");
|
||||
@ -391,8 +439,23 @@ clutter_backend_real_get_features (ClutterBackend *backend)
|
||||
return flags;
|
||||
}
|
||||
|
||||
static const char *allowed_backends;
|
||||
|
||||
static ClutterBackend * (* custom_backend_func) (void);
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
ClutterBackend * (* create_backend) (void);
|
||||
} available_backends[] = {
|
||||
#ifdef CLUTTER_WINDOWING_X11
|
||||
{ CLUTTER_WINDOWING_X11, clutter_backend_x11_new },
|
||||
#endif
|
||||
#ifdef CLUTTER_WINDOWING_EGL
|
||||
{ CLUTTER_WINDOWING_EGL, clutter_backend_egl_native_new },
|
||||
#endif
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
void
|
||||
clutter_set_custom_backend_func (ClutterBackend *(* func) (void))
|
||||
{
|
||||
@ -402,23 +465,75 @@ clutter_set_custom_backend_func (ClutterBackend *(* func) (void))
|
||||
ClutterBackend *
|
||||
_clutter_create_backend (void)
|
||||
{
|
||||
const char *backends_list;
|
||||
ClutterBackend *retval;
|
||||
gboolean allow_any;
|
||||
char **backends;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (custom_backend_func, NULL);
|
||||
if (custom_backend_func)
|
||||
{
|
||||
retval = custom_backend_func ();
|
||||
|
||||
retval = custom_backend_func ();
|
||||
if (!retval)
|
||||
g_error ("Failed to create custom backend.");
|
||||
if (!retval)
|
||||
g_error ("Failed to create custom backend.");
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (allowed_backends == NULL)
|
||||
allowed_backends = "*";
|
||||
|
||||
allow_any = strstr (allowed_backends, "*") != NULL;
|
||||
|
||||
backends_list = g_getenv ("CLUTTER_BACKEND");
|
||||
if (backends_list == NULL)
|
||||
backends_list = allowed_backends;
|
||||
|
||||
backends = g_strsplit (backends_list, ",", 0);
|
||||
|
||||
retval = NULL;
|
||||
|
||||
for (i = 0; retval == NULL && backends[i] != NULL; i++)
|
||||
{
|
||||
const char *backend = backends[i];
|
||||
gboolean is_any = g_str_equal (backend, "*");
|
||||
int j;
|
||||
|
||||
for (j = 0; available_backends[j].name != NULL; j++)
|
||||
{
|
||||
if ((is_any && allow_any) ||
|
||||
(is_any && strstr (allowed_backends, available_backends[j].name)) ||
|
||||
g_str_equal (backend, available_backends[j].name))
|
||||
{
|
||||
retval = available_backends[j].create_backend ();
|
||||
if (retval != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (backends);
|
||||
|
||||
if (retval == NULL)
|
||||
g_error ("No default Clutter backend found.");
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_real_init_events (ClutterBackend *backend)
|
||||
{
|
||||
g_error ("Unknown input backend");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_class_init (ClutterBackendClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_backend_dispose;
|
||||
gobject_class->finalize = clutter_backend_finalize;
|
||||
|
||||
/**
|
||||
* ClutterBackend::resolution-changed:
|
||||
@ -474,6 +589,7 @@ clutter_backend_class_init (ClutterBackendClass *klass)
|
||||
klass->resolution_changed = clutter_backend_real_resolution_changed;
|
||||
klass->font_changed = clutter_backend_real_font_changed;
|
||||
|
||||
klass->init_events = clutter_backend_real_init_events;
|
||||
klass->create_context = clutter_backend_real_create_context;
|
||||
klass->get_features = clutter_backend_real_get_features;
|
||||
}
|
||||
@ -612,6 +728,17 @@ _clutter_backend_get_features (ClutterBackend *backend)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_init_events (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
g_assert (CLUTTER_IS_BACKEND (backend));
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
klass->init_events (backend);
|
||||
}
|
||||
|
||||
gfloat
|
||||
_clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||
PangoFontDescription *font_desc)
|
||||
@ -626,6 +753,31 @@ _clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||
return backend->units_per_em;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_copy_event_data (ClutterBackend *backend,
|
||||
const ClutterEvent *src,
|
||||
ClutterEvent *dest)
|
||||
{
|
||||
ClutterSeatClass *seat_class;
|
||||
ClutterSeat *seat;
|
||||
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
seat_class = CLUTTER_SEAT_GET_CLASS (seat);
|
||||
seat_class->copy_event_data (seat, src, dest);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_free_event_data (ClutterBackend *backend,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterSeatClass *seat_class;
|
||||
ClutterSeat *seat;
|
||||
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
seat_class = CLUTTER_SEAT_GET_CLASS (seat);
|
||||
seat_class->free_event_data (seat, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_get_default_backend:
|
||||
*
|
||||
@ -795,6 +947,31 @@ clutter_backend_get_cogl_context (ClutterBackend *backend)
|
||||
return backend->cogl_context;
|
||||
}
|
||||
|
||||
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
/**
|
||||
* clutter_wayland_set_compositor_display:
|
||||
* @display: A compositor side struct wl_display pointer
|
||||
*
|
||||
* This informs Clutter of your compositor side Wayland display
|
||||
* object. This must be called before calling clutter_init().
|
||||
*
|
||||
* Since: 1.8
|
||||
* Stability: unstable
|
||||
*/
|
||||
void
|
||||
clutter_wayland_set_compositor_display (void *display)
|
||||
{
|
||||
if (_clutter_context_is_initialized ())
|
||||
{
|
||||
g_warning ("%s() can only be used before calling clutter_init()",
|
||||
G_STRFUNC);
|
||||
return;
|
||||
}
|
||||
|
||||
_wayland_compositor_display = display;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
clutter_set_allowed_drivers (const char *drivers)
|
||||
{
|
||||
@ -869,16 +1046,3 @@ 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);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include <clutter/clutter-config.h>
|
||||
#include <clutter/clutter-keymap.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-seat.h>
|
||||
|
@ -59,7 +59,7 @@
|
||||
ClutterMargin *
|
||||
clutter_margin_new (void)
|
||||
{
|
||||
return g_new0 (ClutterMargin, 1);
|
||||
return g_slice_new0 (ClutterMargin);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,7 +77,7 @@ ClutterMargin *
|
||||
clutter_margin_copy (const ClutterMargin *margin_)
|
||||
{
|
||||
if (G_LIKELY (margin_ != NULL))
|
||||
return g_memdup2 (margin_, sizeof (ClutterMargin));
|
||||
return g_slice_dup (ClutterMargin, margin_);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -95,9 +95,198 @@ void
|
||||
clutter_margin_free (ClutterMargin *margin_)
|
||||
{
|
||||
if (G_LIKELY (margin_ != NULL))
|
||||
g_free (margin_);
|
||||
g_slice_free (ClutterMargin, margin_);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterMargin, clutter_margin,
|
||||
clutter_margin_copy,
|
||||
clutter_margin_free)
|
||||
|
||||
/**
|
||||
* ClutterMatrix:
|
||||
*
|
||||
* A type representing a 4x4 matrix.
|
||||
*
|
||||
* It is identicaly to #CoglMatrix.
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
|
||||
static gpointer
|
||||
clutter_matrix_copy (gpointer data)
|
||||
{
|
||||
return cogl_matrix_copy (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_matrix_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
gdouble progress,
|
||||
GValue *retval)
|
||||
{
|
||||
const ClutterMatrix *matrix1 = g_value_get_boxed (a);
|
||||
const ClutterMatrix *matrix2 = g_value_get_boxed (b);
|
||||
graphene_point3d_t scale1 = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f);
|
||||
float shear1[3] = { 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t rotate1 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
graphene_point3d_t translate1 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
ClutterVertex4 perspective1 = { 0.f, 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t scale2 = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f);
|
||||
float shear2[3] = { 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t rotate2 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
graphene_point3d_t translate2 = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
ClutterVertex4 perspective2 = { 0.f, 0.f, 0.f, 0.f };
|
||||
graphene_point3d_t scale_res = GRAPHENE_POINT3D_INIT (1.f, 1.f, 1.f);
|
||||
float shear_res = 0.f;
|
||||
graphene_point3d_t rotate_res = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
graphene_point3d_t translate_res = GRAPHENE_POINT3D_INIT_ZERO;
|
||||
ClutterVertex4 perspective_res = { 0.f, 0.f, 0.f, 0.f };
|
||||
ClutterMatrix res;
|
||||
|
||||
clutter_matrix_init_identity (&res);
|
||||
|
||||
_clutter_util_matrix_decompose (matrix1,
|
||||
&scale1, shear1, &rotate1, &translate1,
|
||||
&perspective1);
|
||||
_clutter_util_matrix_decompose (matrix2,
|
||||
&scale2, shear2, &rotate2, &translate2,
|
||||
&perspective2);
|
||||
|
||||
/* perspective */
|
||||
_clutter_util_vertex4_interpolate (&perspective1, &perspective2, progress, &perspective_res);
|
||||
res.wx = perspective_res.x;
|
||||
res.wy = perspective_res.y;
|
||||
res.wz = perspective_res.z;
|
||||
res.ww = perspective_res.w;
|
||||
|
||||
/* translation */
|
||||
graphene_point3d_interpolate (&translate1, &translate2, progress, &translate_res);
|
||||
cogl_matrix_translate (&res, translate_res.x, translate_res.y, translate_res.z);
|
||||
|
||||
/* rotation */
|
||||
graphene_point3d_interpolate (&rotate1, &rotate2, progress, &rotate_res);
|
||||
cogl_matrix_rotate (&res, rotate_res.x, 1.0f, 0.0f, 0.0f);
|
||||
cogl_matrix_rotate (&res, rotate_res.y, 0.0f, 1.0f, 0.0f);
|
||||
cogl_matrix_rotate (&res, rotate_res.z, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
/* skew */
|
||||
shear_res = shear1[2] + (shear2[2] - shear1[2]) * progress; /* YZ */
|
||||
if (shear_res != 0.f)
|
||||
_clutter_util_matrix_skew_yz (&res, shear_res);
|
||||
|
||||
shear_res = shear1[1] + (shear2[1] - shear1[1]) * progress; /* XZ */
|
||||
if (shear_res != 0.f)
|
||||
_clutter_util_matrix_skew_xz (&res, shear_res);
|
||||
|
||||
shear_res = shear1[0] + (shear2[0] - shear1[0]) * progress; /* XY */
|
||||
if (shear_res != 0.f)
|
||||
_clutter_util_matrix_skew_xy (&res, shear_res);
|
||||
|
||||
/* scale */
|
||||
graphene_point3d_interpolate (&scale1, &scale2, progress, &scale_res);
|
||||
cogl_matrix_scale (&res, scale_res.x, scale_res.y, scale_res.z);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterMatrix, clutter_matrix,
|
||||
clutter_matrix_copy,
|
||||
clutter_matrix_free,
|
||||
CLUTTER_REGISTER_INTERVAL_PROGRESS (clutter_matrix_progress))
|
||||
|
||||
/**
|
||||
* clutter_matrix_alloc:
|
||||
*
|
||||
* Allocates enough memory to hold a #ClutterMatrix.
|
||||
*
|
||||
* Return value: (transfer full): the newly allocated #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterMatrix, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_free:
|
||||
* @matrix: (allow-none): a #ClutterMatrix
|
||||
*
|
||||
* Frees the memory allocated by clutter_matrix_alloc().
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
void
|
||||
clutter_matrix_free (ClutterMatrix *matrix)
|
||||
{
|
||||
cogl_matrix_free (matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_init_identity:
|
||||
* @matrix: a #ClutterMatrix
|
||||
*
|
||||
* Initializes @matrix with the identity matrix, i.e.:
|
||||
*
|
||||
* |[
|
||||
* .xx = 1.0, .xy = 0.0, .xz = 0.0, .xw = 0.0
|
||||
* .yx = 0.0, .yy = 1.0, .yz = 0.0, .yw = 0.0
|
||||
* .zx = 0.0, .zy = 0.0, .zz = 1.0, .zw = 0.0
|
||||
* .wx = 0.0, .wy = 0.0, .wz = 0.0, .ww = 1.0
|
||||
* ]|
|
||||
*
|
||||
* Return value: (transfer none): the initialized #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_init_identity (ClutterMatrix *matrix)
|
||||
{
|
||||
cogl_matrix_init_identity (matrix);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_init_from_array:
|
||||
* @matrix: a #ClutterMatrix
|
||||
* @values: (array fixed-size=16): a C array of 16 floating point values,
|
||||
* representing a 4x4 matrix, with column-major order
|
||||
*
|
||||
* Initializes @matrix with the contents of a C array of floating point
|
||||
* values.
|
||||
*
|
||||
* Return value: (transfer none): the initialzed #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_init_from_array (ClutterMatrix *matrix,
|
||||
const float values[16])
|
||||
{
|
||||
cogl_matrix_init_from_array (matrix, values);
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_matrix_init_from_matrix:
|
||||
* @a: the #ClutterMatrix to initialize
|
||||
* @b: the #ClutterMatrix to copy
|
||||
*
|
||||
* Initializes the #ClutterMatrix @a with the contents of the
|
||||
* #ClutterMatrix @b.
|
||||
*
|
||||
* Return value: (transfer none): the initialized #ClutterMatrix
|
||||
*
|
||||
* Since: 1.12
|
||||
*/
|
||||
ClutterMatrix *
|
||||
clutter_matrix_init_from_matrix (ClutterMatrix *a,
|
||||
const ClutterMatrix *b)
|
||||
{
|
||||
return memcpy (a, b, sizeof (ClutterMatrix));
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
#undef CBZ_L2T_INTERPOLATION
|
||||
|
||||
/****************************************************************************
|
||||
* ClutterBezier -- representation of a cubic bezier curve *
|
||||
* ClutterBezier -- represenation of a cubic bezier curve *
|
||||
* (private; a building block for the public bspline object) *
|
||||
****************************************************************************/
|
||||
|
||||
@ -104,7 +104,7 @@ struct _ClutterBezier
|
||||
ClutterBezier *
|
||||
_clutter_bezier_new (void)
|
||||
{
|
||||
return g_new0 (ClutterBezier, 1);
|
||||
return g_slice_new0 (ClutterBezier);
|
||||
}
|
||||
|
||||
void
|
||||
@ -112,7 +112,7 @@ _clutter_bezier_free (ClutterBezier * b)
|
||||
{
|
||||
if (G_LIKELY (b))
|
||||
{
|
||||
g_free (b);
|
||||
g_slice_free (ClutterBezier, b);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ sqrti (int number)
|
||||
* algorithm does not calculate the square root, but its reciprocal ('y'
|
||||
* below), which is only at the end turned to the inverse value. In order
|
||||
* for the algorithm to produce satisfactory results, the reciprocal value
|
||||
* must be represented with sufficient precision; the 16.16 we use
|
||||
* must be represented with sufficient precission; the 16.16 we use
|
||||
* elsewhere in clutter is not good enough, and 10.22 is used instead.
|
||||
*/
|
||||
_FixedT x;
|
||||
@ -236,7 +236,7 @@ sqrti (int number)
|
||||
/* Now, we convert the float to 10.22 fixed. We exploit the mechanism
|
||||
* described at http://www.d6.com/users/checker/pdfs/gdmfp.pdf.
|
||||
*
|
||||
* We want 22 bit fraction; a single precision float uses 23 bit
|
||||
* We want 22 bit fraction; a single precission float uses 23 bit
|
||||
* mantisa, so we only need to add 2^(23-22) (no need for the 1.5
|
||||
* multiplier as we are only dealing with positive numbers).
|
||||
*
|
||||
@ -256,7 +256,7 @@ sqrti (int number)
|
||||
flt2.i = (flt2.i >> 11) * (y_1 >> 11);
|
||||
|
||||
/* If the original argument is less than 342, we do another
|
||||
* iteration to improve precision (for arguments >= 342, the single
|
||||
* iteration to improve precission (for arguments >= 342, the single
|
||||
* iteration produces generally better results).
|
||||
*/
|
||||
if (x < 171)
|
||||
|
@ -189,7 +189,7 @@ binding_entry_new (const gchar *name,
|
||||
|
||||
modifiers = modifiers & BINDING_MOD_MASK;
|
||||
|
||||
entry = g_new0 (ClutterBindingEntry, 1);
|
||||
entry = g_slice_new (ClutterBindingEntry);
|
||||
entry->key_val = key_val;
|
||||
entry->modifiers = modifiers;
|
||||
entry->name = (gchar *) g_intern_string (name);
|
||||
@ -221,7 +221,7 @@ binding_entry_free (gpointer data)
|
||||
|
||||
g_closure_unref (entry->closure);
|
||||
|
||||
g_free (entry);
|
||||
g_slice_free (ClutterBindingEntry, entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-blur-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
@ -1,431 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Endless OS Foundation, LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter-blur-private.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
|
||||
/**
|
||||
* SECTION:clutter-blur
|
||||
* @short_description: Blur textures
|
||||
*
|
||||
* #ClutterBlur is a moderately fast gaussian blur implementation.
|
||||
*
|
||||
* # Optimizations
|
||||
*
|
||||
* There are a number of optimizations in place to make this blur implementation
|
||||
* real-time. All in all, the implementation performs best when using large
|
||||
* blur-radii that allow downscaling the texture to smaller sizes, at small
|
||||
* radii where no downscaling is possible this can easily halve the framerate.
|
||||
*
|
||||
* ## Multipass
|
||||
*
|
||||
* It is implemented in 2 passes: vertical and horizontal.
|
||||
*
|
||||
* ## Downscaling
|
||||
*
|
||||
* #ClutterBlur uses dynamic downscaling to speed up blurring. Downscaling
|
||||
* happens in factors of 2 (the image is downscaled either by 2, 4, 8, 16, …)
|
||||
* and depends on the blur radius, the texture size, among others.
|
||||
*
|
||||
* The texture is drawn into a downscaled framebuffer; the blur passes are
|
||||
* applied on the downscaled texture contents; and finally, the blurred
|
||||
* contents are drawn
|
||||
* upscaled again.
|
||||
*
|
||||
* ## Hardware Interpolation
|
||||
*
|
||||
* This blur implementation cuts down the number of sampling operations by
|
||||
* exploiting the hardware interpolation that is performed when sampling between
|
||||
* pixel boundaries. This technique is described at:
|
||||
*
|
||||
* http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
|
||||
*
|
||||
* ## Incremental gauss-factor calculation
|
||||
*
|
||||
* The kernel values for the gaussian kernel are computed incrementally instead
|
||||
* of running the expensive calculations multiple times inside the blur shader.
|
||||
* The implementation is based on the algorithm presented by K. Turkowski in
|
||||
* GPU Gems 3, chapter 40:
|
||||
*
|
||||
* https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch40.html
|
||||
*
|
||||
*/
|
||||
|
||||
static const char *gaussian_blur_glsl_declarations =
|
||||
"uniform float sigma; \n"
|
||||
"uniform float pixel_step; \n"
|
||||
"uniform vec2 direction; \n";
|
||||
|
||||
static const char *gaussian_blur_glsl =
|
||||
" vec2 uv = vec2 (cogl_tex_coord.st); \n"
|
||||
" \n"
|
||||
" vec3 gauss_coefficient; \n"
|
||||
" gauss_coefficient.x = 1.0 / (sqrt (2.0 * 3.14159265) * sigma); \n"
|
||||
" gauss_coefficient.y = exp (-0.5 / (sigma * sigma)); \n"
|
||||
" gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y; \n"
|
||||
" \n"
|
||||
" float gauss_coefficient_total = gauss_coefficient.x; \n"
|
||||
" \n"
|
||||
" vec4 ret = texture2D (cogl_sampler, uv) * gauss_coefficient.x; \n"
|
||||
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
|
||||
" \n"
|
||||
" int n_steps = int (ceil (1.5 * sigma)) * 2; \n"
|
||||
" \n"
|
||||
" for (int i = 1; i <= n_steps; i += 2) { \n"
|
||||
" float coefficient_subtotal = gauss_coefficient.x; \n"
|
||||
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
|
||||
" coefficient_subtotal += gauss_coefficient.x; \n"
|
||||
" \n"
|
||||
" float gauss_ratio = gauss_coefficient.x / coefficient_subtotal; \n"
|
||||
" \n"
|
||||
" float foffset = float (i) + gauss_ratio; \n"
|
||||
" vec2 offset = direction * foffset * pixel_step; \n"
|
||||
" \n"
|
||||
" ret += texture2D (cogl_sampler, uv + offset) * coefficient_subtotal; \n"
|
||||
" ret += texture2D (cogl_sampler, uv - offset) * coefficient_subtotal; \n"
|
||||
" \n"
|
||||
" gauss_coefficient_total += 2.0 * coefficient_subtotal; \n"
|
||||
" gauss_coefficient.xy *= gauss_coefficient.yz; \n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" cogl_texel = ret / gauss_coefficient_total; \n";
|
||||
|
||||
#define MIN_DOWNSCALE_SIZE 256.f
|
||||
#define MAX_SIGMA 6.f
|
||||
|
||||
enum
|
||||
{
|
||||
VERTICAL,
|
||||
HORIZONTAL,
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglPipeline *pipeline;
|
||||
CoglTexture *texture;
|
||||
int orientation;
|
||||
} BlurPass;
|
||||
|
||||
struct _ClutterBlur
|
||||
{
|
||||
CoglTexture *source_texture;
|
||||
float sigma;
|
||||
float downscale_factor;
|
||||
|
||||
BlurPass pass[2];
|
||||
};
|
||||
|
||||
static CoglPipeline*
|
||||
create_blur_pipeline (void)
|
||||
{
|
||||
static CoglPipelineKey blur_pipeline_key = "clutter-blur-pipeline-private";
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglPipeline *blur_pipeline;
|
||||
|
||||
blur_pipeline =
|
||||
cogl_context_get_named_pipeline (ctx, &blur_pipeline_key);
|
||||
|
||||
if (G_UNLIKELY (blur_pipeline == NULL))
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
|
||||
blur_pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_layer_null_texture (blur_pipeline, 0);
|
||||
cogl_pipeline_set_layer_filters (blur_pipeline,
|
||||
0,
|
||||
COGL_PIPELINE_FILTER_LINEAR,
|
||||
COGL_PIPELINE_FILTER_LINEAR);
|
||||
cogl_pipeline_set_layer_wrap_mode (blur_pipeline,
|
||||
0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
gaussian_blur_glsl_declarations,
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet, gaussian_blur_glsl);
|
||||
cogl_pipeline_add_layer_snippet (blur_pipeline, 0, snippet);
|
||||
cogl_object_unref (snippet);
|
||||
|
||||
cogl_context_set_named_pipeline (ctx, &blur_pipeline_key, blur_pipeline);
|
||||
}
|
||||
|
||||
return cogl_pipeline_copy (blur_pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
update_blur_uniforms (ClutterBlur *blur,
|
||||
BlurPass *pass)
|
||||
{
|
||||
gboolean vertical = pass->orientation == VERTICAL;
|
||||
int sigma_uniform;
|
||||
int pixel_step_uniform;
|
||||
int direction_uniform;
|
||||
|
||||
pixel_step_uniform =
|
||||
cogl_pipeline_get_uniform_location (pass->pipeline, "pixel_step");
|
||||
if (pixel_step_uniform > -1)
|
||||
{
|
||||
float pixel_step;
|
||||
|
||||
if (vertical)
|
||||
pixel_step = 1.f / cogl_texture_get_height (pass->texture);
|
||||
else
|
||||
pixel_step = 1.f / cogl_texture_get_width (pass->texture);
|
||||
|
||||
cogl_pipeline_set_uniform_1f (pass->pipeline,
|
||||
pixel_step_uniform,
|
||||
pixel_step);
|
||||
}
|
||||
|
||||
sigma_uniform = cogl_pipeline_get_uniform_location (pass->pipeline, "sigma");
|
||||
if (sigma_uniform > -1)
|
||||
{
|
||||
cogl_pipeline_set_uniform_1f (pass->pipeline,
|
||||
sigma_uniform,
|
||||
blur->sigma / blur->downscale_factor);
|
||||
}
|
||||
|
||||
direction_uniform =
|
||||
cogl_pipeline_get_uniform_location (pass->pipeline, "direction");
|
||||
if (direction_uniform > -1)
|
||||
{
|
||||
gboolean horizontal = !vertical;
|
||||
float direction[2] = {
|
||||
horizontal,
|
||||
vertical,
|
||||
};
|
||||
|
||||
cogl_pipeline_set_uniform_float (pass->pipeline,
|
||||
direction_uniform,
|
||||
2, 1,
|
||||
direction);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_fbo (ClutterBlur *blur,
|
||||
BlurPass *pass)
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
float scaled_height;
|
||||
float scaled_width;
|
||||
float height;
|
||||
float width;
|
||||
|
||||
g_clear_pointer (&pass->texture, cogl_object_unref);
|
||||
g_clear_object (&pass->framebuffer);
|
||||
|
||||
width = cogl_texture_get_width (blur->source_texture);
|
||||
height = cogl_texture_get_height (blur->source_texture);
|
||||
scaled_width = floorf (width / blur->downscale_factor);
|
||||
scaled_height = floorf (height / blur->downscale_factor);
|
||||
|
||||
pass->texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx,
|
||||
scaled_width,
|
||||
scaled_height));
|
||||
if (!pass->texture)
|
||||
return FALSE;
|
||||
|
||||
pass->framebuffer =
|
||||
COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (pass->texture));
|
||||
if (!pass->framebuffer)
|
||||
{
|
||||
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cogl_framebuffer_orthographic (pass->framebuffer,
|
||||
0.0, 0.0,
|
||||
scaled_width,
|
||||
scaled_height,
|
||||
0.0, 1.0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
setup_blur_pass (ClutterBlur *blur,
|
||||
BlurPass *pass,
|
||||
int orientation,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
pass->orientation = orientation;
|
||||
pass->pipeline = create_blur_pipeline ();
|
||||
cogl_pipeline_set_layer_texture (pass->pipeline, 0, texture);
|
||||
|
||||
if (!create_fbo (blur, pass))
|
||||
return FALSE;
|
||||
|
||||
update_blur_uniforms (blur, pass);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static float
|
||||
calculate_downscale_factor (float width,
|
||||
float height,
|
||||
float sigma)
|
||||
{
|
||||
float downscale_factor = 1.f;
|
||||
float scaled_width = width;
|
||||
float scaled_height = height;
|
||||
float scaled_sigma = sigma;
|
||||
|
||||
/* This is the algorithm used by Firefox; keep downscaling until either the
|
||||
* blur radius is lower than the threshold, or the downscaled texture is too
|
||||
* small.
|
||||
*/
|
||||
while (scaled_sigma > MAX_SIGMA &&
|
||||
scaled_width > MIN_DOWNSCALE_SIZE &&
|
||||
scaled_height > MIN_DOWNSCALE_SIZE)
|
||||
{
|
||||
downscale_factor *= 2.f;
|
||||
|
||||
scaled_width = width / downscale_factor;
|
||||
scaled_height = height / downscale_factor;
|
||||
scaled_sigma = sigma / downscale_factor;
|
||||
}
|
||||
|
||||
return downscale_factor;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_blur_pass (BlurPass *pass)
|
||||
{
|
||||
CoglColor transparent;
|
||||
|
||||
cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
|
||||
|
||||
cogl_framebuffer_clear (pass->framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR,
|
||||
&transparent);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (pass->framebuffer,
|
||||
pass->pipeline,
|
||||
0, 0,
|
||||
cogl_texture_get_width (pass->texture),
|
||||
cogl_texture_get_height (pass->texture));
|
||||
}
|
||||
|
||||
static void
|
||||
clear_blur_pass (BlurPass *pass)
|
||||
{
|
||||
g_clear_pointer (&pass->pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&pass->texture, cogl_object_unref);
|
||||
g_clear_object (&pass->framebuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_new:
|
||||
* @texture: a #CoglTexture
|
||||
* @sigma: blur sigma
|
||||
*
|
||||
* Creates a new #ClutterBlur.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): A newly created #ClutterBlur
|
||||
*/
|
||||
ClutterBlur *
|
||||
clutter_blur_new (CoglTexture *texture,
|
||||
float sigma)
|
||||
{
|
||||
ClutterBlur *blur;
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
BlurPass *hpass;
|
||||
BlurPass *vpass;
|
||||
|
||||
g_return_val_if_fail (texture != NULL, NULL);
|
||||
g_return_val_if_fail (sigma >= 0.0, NULL);
|
||||
|
||||
width = cogl_texture_get_width (texture);
|
||||
height = cogl_texture_get_height (texture);
|
||||
|
||||
blur = g_new0 (ClutterBlur, 1);
|
||||
blur->sigma = sigma;
|
||||
blur->source_texture = cogl_object_ref (texture);
|
||||
blur->downscale_factor = calculate_downscale_factor (width, height, sigma);
|
||||
|
||||
if (G_APPROX_VALUE (sigma, 0.0, FLT_EPSILON))
|
||||
goto out;
|
||||
|
||||
vpass = &blur->pass[VERTICAL];
|
||||
hpass = &blur->pass[HORIZONTAL];
|
||||
|
||||
if (!setup_blur_pass (blur, vpass, VERTICAL, texture) ||
|
||||
!setup_blur_pass (blur, hpass, HORIZONTAL, vpass->texture))
|
||||
{
|
||||
clutter_blur_free (blur);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
return g_steal_pointer (&blur);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_apply:
|
||||
* @blur: a #ClutterBlur
|
||||
*
|
||||
* Applies the blur. The resulting texture can be retrieved by
|
||||
* clutter_blur_get_texture().
|
||||
*/
|
||||
void
|
||||
clutter_blur_apply (ClutterBlur *blur)
|
||||
{
|
||||
if (G_APPROX_VALUE (blur->sigma, 0.0, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
apply_blur_pass (&blur->pass[VERTICAL]);
|
||||
apply_blur_pass (&blur->pass[HORIZONTAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_get_texture:
|
||||
* @blur: a #ClutterBlur
|
||||
*
|
||||
* Retrieves the texture where the blurred contents are stored. The
|
||||
* contents are undefined until clutter_blur_apply() is called.
|
||||
*
|
||||
* Returns: (transfer none): a #CoglTexture
|
||||
*/
|
||||
CoglTexture *
|
||||
clutter_blur_get_texture (ClutterBlur *blur)
|
||||
{
|
||||
if (G_APPROX_VALUE (blur->sigma, 0.0, FLT_EPSILON))
|
||||
return blur->source_texture;
|
||||
else
|
||||
return blur->pass[HORIZONTAL].texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_free:
|
||||
* @blur: A #ClutterBlur
|
||||
*
|
||||
* Frees @blur.
|
||||
*/
|
||||
void
|
||||
clutter_blur_free (ClutterBlur *blur)
|
||||
{
|
||||
g_assert (blur);
|
||||
|
||||
clear_blur_pass (&blur->pass[VERTICAL]);
|
||||
clear_blur_pass (&blur->pass[HORIZONTAL]);
|
||||
cogl_clear_object (&blur->source_texture);
|
||||
g_free (blur);
|
||||
}
|
@ -39,7 +39,7 @@
|
||||
* #ClutterActor:y-expand are set, the available size
|
||||
* - honours the #ClutterActor's #ClutterActor:x-align and #ClutterActor:y-align properties
|
||||
* to fill the available size
|
||||
* - if the #ClutterBoxLayout:homogeneous boolean property is set, then all widgets will
|
||||
* - if the #ClutterBoxLayout:homogeneous boolean propert is set, then all widgets will
|
||||
* get the same size, ignoring expand settings and the preferred sizes
|
||||
*
|
||||
* It is possible to control the spacing between children of a
|
||||
@ -719,7 +719,7 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
|
||||
|
||||
if (priv->is_homogeneous)
|
||||
{
|
||||
/* If were homogeneous we still need to run the above loop to get the
|
||||
/* If were homogenous we still need to run the above loop to get the
|
||||
* minimum sizes for children that are not going to fill
|
||||
*/
|
||||
if (priv->orientation == CLUTTER_ORIENTATION_VERTICAL)
|
||||
@ -1218,7 +1218,7 @@ clutter_box_layout_get_homogeneous (ClutterBoxLayout *layout)
|
||||
* @pack_start: %TRUE if the @layout should pack children at the
|
||||
* beginning of the layout
|
||||
*
|
||||
* Sets whether children of @layout should be laid out by appending
|
||||
* Sets whether children of @layout should be layed out by appending
|
||||
* them or by prepending them
|
||||
*
|
||||
* Since: 1.2
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-brightness-contrast-effect.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
@ -4,5 +4,11 @@
|
||||
/* List of Cogl drivers */
|
||||
#mesondefine CLUTTER_DRIVERS
|
||||
|
||||
/* Have evdev support for input handling */
|
||||
#mesondefine HAVE_EVDEV
|
||||
|
||||
/* Building with libwacom for advanced tablet management */
|
||||
#mesondefine HAVE_LIBWACOM
|
||||
|
||||
/* Supports PangoFt2 */
|
||||
#mesondefine HAVE_PANGO_FT2
|
||||
|
@ -50,6 +50,8 @@
|
||||
|
||||
#include "clutter-canvas.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-cairo.h"
|
||||
|
@ -114,7 +114,7 @@ struct _ClutterClickActionPrivate
|
||||
gint drag_threshold;
|
||||
|
||||
guint press_button;
|
||||
ClutterInputDevice *press_device;
|
||||
gint press_device_id;
|
||||
ClutterEventSequence *press_sequence;
|
||||
ClutterModifierType modifier_state;
|
||||
gfloat press_x;
|
||||
@ -272,23 +272,6 @@ click_action_cancel_long_press (ClutterClickAction *action)
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
event_within_drag_threshold (ClutterClickAction *click_action,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterClickActionPrivate *priv =
|
||||
clutter_click_action_get_instance_private (click_action);
|
||||
float motion_x, motion_y;
|
||||
float delta_x, delta_y;
|
||||
|
||||
clutter_event_get_coords (event, &motion_x, &motion_y);
|
||||
|
||||
delta_x = ABS (motion_x - priv->press_x);
|
||||
delta_y = ABS (motion_y - priv->press_y);
|
||||
|
||||
return delta_x <= priv->drag_threshold && delta_y <= priv->drag_threshold;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
@ -316,7 +299,7 @@ on_event (ClutterActor *actor,
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
priv->press_button = has_button ? clutter_event_get_button (event) : 0;
|
||||
priv->press_device = clutter_event_get_device (event);
|
||||
priv->press_device_id = clutter_event_get_device_id (event);
|
||||
priv->press_sequence = clutter_event_get_event_sequence (event);
|
||||
priv->modifier_state = clutter_event_get_state (event);
|
||||
clutter_event_get_coords (event, &priv->press_x, &priv->press_y);
|
||||
@ -387,7 +370,7 @@ on_captured_event (ClutterActor *stage,
|
||||
|
||||
if ((has_button && clutter_event_get_button (event) != priv->press_button) ||
|
||||
(has_button && clutter_event_get_click_count (event) != 1) ||
|
||||
clutter_event_get_device (event) != priv->press_device ||
|
||||
clutter_event_get_device_id (event) != priv->press_device_id ||
|
||||
clutter_event_get_event_sequence (event) != priv->press_sequence)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
@ -419,23 +402,30 @@ on_captured_event (ClutterActor *stage,
|
||||
priv->modifier_state = 0;
|
||||
|
||||
click_action_set_pressed (action, FALSE);
|
||||
|
||||
if (event_within_drag_threshold (action, event))
|
||||
g_signal_emit (action, click_signals[CLICKED], 0, actor);
|
||||
g_signal_emit (action, click_signals[CLICKED], 0, actor);
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
{
|
||||
if (clutter_event_get_device (event) != priv->press_device ||
|
||||
gfloat motion_x, motion_y;
|
||||
gfloat delta_x, delta_y;
|
||||
|
||||
if (clutter_event_get_device_id (event) != priv->press_device_id ||
|
||||
clutter_event_get_event_sequence (event) != priv->press_sequence)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
if (!priv->is_held)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
|
||||
if (!event_within_drag_threshold (action, event))
|
||||
clutter_click_action_release (action);
|
||||
clutter_event_get_coords (event, &motion_x, &motion_y);
|
||||
|
||||
delta_x = ABS (motion_x - priv->press_x);
|
||||
delta_y = ABS (motion_y - priv->press_y);
|
||||
|
||||
if (delta_x > priv->drag_threshold ||
|
||||
delta_y > priv->drag_threshold)
|
||||
click_action_cancel_long_press (action);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-clone.h"
|
||||
#include "clutter-debug.h"
|
||||
@ -120,17 +121,20 @@ clutter_clone_get_preferred_height (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_apply_transform (ClutterActor *self,
|
||||
graphene_matrix_t *matrix)
|
||||
clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
|
||||
{
|
||||
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
|
||||
|
||||
|
||||
if (priv->clone_source)
|
||||
graphene_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
|
||||
|
||||
/* First chain up and apply all the standard ClutterActor
|
||||
* transformations... */
|
||||
CLUTTER_ACTOR_CLASS (clutter_clone_parent_class)->apply_transform (self,
|
||||
matrix);
|
||||
|
||||
/* if we don't have a source, nothing else to do */
|
||||
if (priv->clone_source == NULL)
|
||||
return;
|
||||
|
||||
cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -195,7 +199,7 @@ clutter_clone_get_paint_volume (ClutterActor *actor,
|
||||
if (priv->clone_source == NULL)
|
||||
return TRUE;
|
||||
|
||||
/* query the volume of the source actor and simply masquerade it as
|
||||
/* query the volume of the source actor and simply masquarade it as
|
||||
* the clones volume... */
|
||||
source_volume = clutter_actor_get_paint_volume (priv->clone_source);
|
||||
if (source_volume == NULL)
|
||||
@ -241,13 +245,7 @@ clutter_clone_allocate (ClutterActor *self,
|
||||
*/
|
||||
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_allocate_preferred_size (priv->clone_source);
|
||||
|
||||
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
|
||||
|
||||
|
@ -611,7 +611,7 @@ parse_hsla (ClutterColor *color,
|
||||
/**
|
||||
* clutter_color_from_string:
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
* @str: a string specifying a color
|
||||
* @str: a string specifiying a color
|
||||
*
|
||||
* Parses a string definition of a color, filling the #ClutterColor.red,
|
||||
* #ClutterColor.green, #ClutterColor.blue and #ClutterColor.alpha fields
|
||||
@ -911,7 +911,7 @@ ClutterColor *
|
||||
clutter_color_copy (const ClutterColor *color)
|
||||
{
|
||||
if (G_LIKELY (color != NULL))
|
||||
return g_memdup2 (color, sizeof (ClutterColor));
|
||||
return g_slice_dup (ClutterColor, color);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -928,7 +928,7 @@ void
|
||||
clutter_color_free (ClutterColor *color)
|
||||
{
|
||||
if (G_LIKELY (color != NULL))
|
||||
g_free (color);
|
||||
g_slice_free (ClutterColor, color);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -977,7 +977,7 @@ clutter_color_new (guint8 red,
|
||||
ClutterColor *
|
||||
clutter_color_alloc (void)
|
||||
{
|
||||
return g_new0 (ClutterColor, 1);
|
||||
return g_slice_new0 (ClutterColor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,6 +39,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-colorize-effect.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
22
clutter/clutter/clutter-config.h.in
Normal file
22
clutter/clutter/clutter-config.h.in
Normal file
@ -0,0 +1,22 @@
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_CONFIG_H__
|
||||
#define __CLUTTER_CONFIG_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#mesondefine CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
|
||||
#mesondefine CLUTTER_WINDOWING_X11
|
||||
#mesondefine CLUTTER_INPUT_X11
|
||||
#mesondefine CLUTTER_WINDOWING_GLX
|
||||
#mesondefine CLUTTER_WINDOWING_EGL
|
||||
#mesondefine CLUTTER_INPUT_EVDEV
|
||||
#mesondefine CLUTTER_INPUT_NULL
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_CONFIG_H__ */
|
@ -74,7 +74,7 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
|
||||
* fields in the instance and add the record to a data structure for
|
||||
* subsequent access for #ClutterContainerIface::get_child_meta
|
||||
* @destroy_child_meta: virtual function that gets called when a child is
|
||||
* removed; it should release all resources held by the record
|
||||
* removed; it shuld release all resources held by the record
|
||||
* @get_child_meta: return the record for a container child
|
||||
* @actor_added: class handler for #ClutterContainer::actor-added
|
||||
* @actor_removed: class handler for #ClutterContainer::actor-removed
|
||||
|
@ -22,28 +22,20 @@
|
||||
#include <cairo.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "clutter-macros.h"
|
||||
|
||||
typedef struct _ClutterDamageHistory ClutterDamageHistory;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterDamageHistory * clutter_damage_history_new (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_free (ClutterDamageHistory *history);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
|
||||
int age);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_record (ClutterDamageHistory *history,
|
||||
const cairo_region_t *damage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_damage_history_step (ClutterDamageHistory *history);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
const cairo_region_t * clutter_damage_history_lookup (ClutterDamageHistory *history,
|
||||
int age);
|
||||
|
||||
|
@ -41,7 +41,6 @@ G_BEGIN_DECLS
|
||||
extern guint clutter_debug_flags;
|
||||
extern guint clutter_pick_debug_flags;
|
||||
extern guint clutter_paint_debug_flags;
|
||||
extern int clutter_max_render_time_constant_us;
|
||||
|
||||
void _clutter_debug_messagev (const char *format,
|
||||
va_list var_args) G_GNUC_PRINTF (1, 0);
|
||||
|
@ -53,6 +53,7 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
#include "clutter-deform-effect.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
@ -28,7 +28,7 @@
|
||||
* @see_also: #ClutterEffect, #ClutterOffscreenEffect
|
||||
*
|
||||
* #ClutterDesaturateEffect is a sub-class of #ClutterEffect that
|
||||
* desaturates the color of an actor and its contents. The strength
|
||||
* desaturates the color of an actor and its contents. The strenght
|
||||
* of the desaturation effect is controllable and animatable through
|
||||
* the #ClutterDesaturateEffect:factor property.
|
||||
*
|
||||
@ -41,6 +41,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter-desaturate-effect.h"
|
||||
|
@ -201,8 +201,10 @@ clutter_effect_real_modify_paint_volume (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
static void
|
||||
add_actor_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node)
|
||||
clutter_effect_real_paint_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context,
|
||||
ClutterEffectPaintFlags flags)
|
||||
{
|
||||
ClutterPaintNode *actor_node;
|
||||
ClutterActor *actor;
|
||||
@ -214,15 +216,6 @@ add_actor_node (ClutterEffect *effect,
|
||||
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,
|
||||
@ -238,16 +231,10 @@ clutter_effect_real_paint (ClutterEffect *effect,
|
||||
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect, node,paint_context);
|
||||
|
||||
effect_class->paint_node (effect, node, paint_context, flags);
|
||||
|
||||
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);
|
||||
}
|
||||
effect_class->post_paint (effect, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -368,7 +355,7 @@ _clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
|
||||
* the actor itself so the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY would still
|
||||
* not be set. The effect can detect this case by keeping track of the
|
||||
* last modelview matrix that was used to render the actor and
|
||||
* verifying that it remains the same in the next paint.
|
||||
* veryifying that it remains the same in the next paint.
|
||||
*
|
||||
* Any other effects that are layered on top of the passed in effect
|
||||
* will still be passed the %CLUTTER_EFFECT_PAINT_ACTOR_DIRTY flag. If
|
||||
@ -392,6 +379,7 @@ clutter_effect_queue_repaint (ClutterEffect *effect)
|
||||
/* If the effect has no actor then nothing needs to be done */
|
||||
if (actor != NULL)
|
||||
_clutter_actor_queue_redraw_full (actor,
|
||||
0, /* flags */
|
||||
NULL, /* clip volume */
|
||||
effect /* effect */);
|
||||
}
|
||||
|
@ -14,9 +14,9 @@
|
||||
GType
|
||||
@enum_name@_get_type (void)
|
||||
{
|
||||
static size_t g_enum_type_id = 0;
|
||||
static volatile gsize g_enum_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&g_enum_type_id))
|
||||
if (g_once_init_enter (&g_enum_type_id__volatile))
|
||||
{
|
||||
static const G@Type@Value values[] = {
|
||||
/*** END value-header ***/
|
||||
@ -28,13 +28,14 @@ GType
|
||||
/*** BEGIN value-tail ***/
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
GType id;
|
||||
GType g_enum_type_id;
|
||||
|
||||
id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||
g_enum_type_id =
|
||||
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||
|
||||
g_once_init_leave (&g_enum_type_id, id);
|
||||
g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
|
||||
}
|
||||
|
||||
return g_enum_type_id;
|
||||
return g_enum_type_id__volatile;
|
||||
}
|
||||
/*** END value-tail ***/
|
||||
|
@ -127,7 +127,7 @@ typedef enum /*< prefix=CLUTTER_REQUEST >*/
|
||||
* @CLUTTER_EASE_IN_OUT_QUAD: quadratic tweening, combininig
|
||||
* %CLUTTER_EASE_IN_QUAD and %CLUTTER_EASE_OUT_QUAD
|
||||
* @CLUTTER_EASE_IN_CUBIC: cubic tweening
|
||||
* @CLUTTER_EASE_OUT_CUBIC: cubic tweening, inverse of
|
||||
* @CLUTTER_EASE_OUT_CUBIC: cubic tweening, invers of
|
||||
* %CLUTTER_EASE_IN_CUBIC
|
||||
* @CLUTTER_EASE_IN_OUT_CUBIC: cubic tweening, combining
|
||||
* %CLUTTER_EASE_IN_CUBIC and %CLUTTER_EASE_OUT_CUBIC
|
||||
@ -387,6 +387,44 @@ typedef enum
|
||||
CLUTTER_MODIFIER_MASK = 0x5c001fff
|
||||
} ClutterModifierType;
|
||||
|
||||
/**
|
||||
* ClutterKeyboardA11yFlags:
|
||||
* @CLUTTER_A11Y_KEYBOARD_ENABLED:
|
||||
* @CLUTTER_A11Y_TIMEOUT_ENABLED:
|
||||
* @CLUTTER_A11Y_MOUSE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT:
|
||||
* @CLUTTER_A11Y_BOUNCE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT:
|
||||
* @CLUTTER_A11Y_TOGGLE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_BEEP:
|
||||
* @CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP:
|
||||
*
|
||||
* Keyboard accessibility features applied to a ClutterInputDevice keyboard.
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_A11Y_KEYBOARD_ENABLED = 1 << 0,
|
||||
CLUTTER_A11Y_TIMEOUT_ENABLED = 1 << 1,
|
||||
CLUTTER_A11Y_MOUSE_KEYS_ENABLED = 1 << 2,
|
||||
CLUTTER_A11Y_SLOW_KEYS_ENABLED = 1 << 3,
|
||||
CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS = 1 << 4,
|
||||
CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT = 1 << 5,
|
||||
CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT = 1 << 6,
|
||||
CLUTTER_A11Y_BOUNCE_KEYS_ENABLED = 1 << 7,
|
||||
CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT = 1 << 8,
|
||||
CLUTTER_A11Y_TOGGLE_KEYS_ENABLED = 1 << 9,
|
||||
CLUTTER_A11Y_STICKY_KEYS_ENABLED = 1 << 10,
|
||||
CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF = 1 << 11,
|
||||
CLUTTER_A11Y_STICKY_KEYS_BEEP = 1 << 12,
|
||||
CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13,
|
||||
} ClutterKeyboardA11yFlags;
|
||||
|
||||
/**
|
||||
* ClutterPointerA11yFlags:
|
||||
* @CLUTTER_A11Y_POINTER_ENABLED:
|
||||
@ -475,7 +513,7 @@ typedef enum {
|
||||
* a toplevel, and all parents visible)
|
||||
* @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been
|
||||
* allocated
|
||||
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emitting event
|
||||
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event
|
||||
* signals
|
||||
* @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program
|
||||
* @CLUTTER_ACTOR_NO_LAYOUT: the actor provides an explicit layout management
|
||||
@ -802,8 +840,7 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/
|
||||
CLUTTER_EVENT_NONE = 0,
|
||||
CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0,
|
||||
CLUTTER_EVENT_FLAG_INPUT_METHOD = 1 << 1,
|
||||
CLUTTER_EVENT_FLAG_REPEATED = 1 << 2,
|
||||
CLUTTER_EVENT_FLAG_RELATIVE_MOTION = 1 << 3,
|
||||
CLUTTER_EVENT_FLAG_REPEATED = 1 << 2
|
||||
} ClutterEventFlags;
|
||||
|
||||
/**
|
||||
@ -817,6 +854,10 @@ typedef enum /*< flags prefix=CLUTTER_EVENT >*/
|
||||
* @CLUTTER_BUTTON_PRESS: Pointer button press event
|
||||
* @CLUTTER_BUTTON_RELEASE: Pointer button release event
|
||||
* @CLUTTER_SCROLL: Pointer scroll event
|
||||
* @CLUTTER_STAGE_STATE: Stage state change event
|
||||
* @CLUTTER_DESTROY_NOTIFY: Destroy notification event
|
||||
* @CLUTTER_CLIENT_MESSAGE: Client message event
|
||||
* @CLUTTER_DELETE: Stage delete event
|
||||
* @CLUTTER_TOUCH_BEGIN: A new touch event sequence has started;
|
||||
* event added in 1.10
|
||||
* @CLUTTER_TOUCH_UPDATE: A touch event sequence has been updated;
|
||||
@ -851,6 +892,10 @@ typedef enum /*< prefix=CLUTTER >*/
|
||||
CLUTTER_BUTTON_PRESS,
|
||||
CLUTTER_BUTTON_RELEASE,
|
||||
CLUTTER_SCROLL,
|
||||
CLUTTER_STAGE_STATE,
|
||||
CLUTTER_DESTROY_NOTIFY,
|
||||
CLUTTER_CLIENT_MESSAGE,
|
||||
CLUTTER_DELETE,
|
||||
CLUTTER_TOUCH_BEGIN,
|
||||
CLUTTER_TOUCH_UPDATE,
|
||||
CLUTTER_TOUCH_END,
|
||||
@ -863,11 +908,6 @@ typedef enum /*< prefix=CLUTTER >*/
|
||||
CLUTTER_PAD_BUTTON_RELEASE,
|
||||
CLUTTER_PAD_STRIP,
|
||||
CLUTTER_PAD_RING,
|
||||
CLUTTER_DEVICE_ADDED,
|
||||
CLUTTER_DEVICE_REMOVED,
|
||||
CLUTTER_IM_COMMIT,
|
||||
CLUTTER_IM_DELETE,
|
||||
CLUTTER_IM_PREEDIT,
|
||||
|
||||
CLUTTER_EVENT_LAST /* helper */
|
||||
} ClutterEventType;
|
||||
@ -896,8 +936,22 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
|
||||
CLUTTER_SCROLL_SMOOTH
|
||||
} ClutterScrollDirection;
|
||||
|
||||
/**
|
||||
* ClutterStageState:
|
||||
* @CLUTTER_STAGE_STATE_ACTIVATED: Activated mask
|
||||
*
|
||||
* Stage state masks, used by the #ClutterEvent of type %CLUTTER_STAGE_STATE.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_STAGE_STATE_ACTIVATED = (1 << 3)
|
||||
} ClutterStageState;
|
||||
|
||||
/**
|
||||
* ClutterFeatureFlags:
|
||||
* @CLUTTER_FEATURE_SWAP_THROTTLE: Set if backend throttles buffer swaps.
|
||||
* @CLUTTER_FEATURE_STAGE_STATIC: Set if stage size if fixed (i.e framebuffer)
|
||||
* @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor.
|
||||
* @CLUTTER_FEATURE_SHADERS_GLSL: Set if the backend supports GLSL shaders.
|
||||
@ -912,6 +966,7 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_FEATURE_SWAP_THROTTLE = (1 << 3),
|
||||
CLUTTER_FEATURE_STAGE_STATIC = (1 << 6),
|
||||
CLUTTER_FEATURE_STAGE_CURSOR = (1 << 8),
|
||||
CLUTTER_FEATURE_SHADERS_GLSL = (1 << 9),
|
||||
@ -979,11 +1034,11 @@ typedef enum
|
||||
|
||||
/**
|
||||
* ClutterInputMode:
|
||||
* @CLUTTER_INPUT_MODE_LOGICAL: A logical, virtual device
|
||||
* @CLUTTER_INPUT_MODE_PHYSICAL: A physical device, attached to
|
||||
* a logical device
|
||||
* @CLUTTER_INPUT_MODE_FLOATING: A physical device, not attached
|
||||
* to a logical device
|
||||
* @CLUTTER_INPUT_MODE_MASTER: A master, virtual device
|
||||
* @CLUTTER_INPUT_MODE_SLAVE: A slave, physical device, attached to
|
||||
* a master device
|
||||
* @CLUTTER_INPUT_MODE_FLOATING: A slave, physical device, not attached
|
||||
* to a master device
|
||||
*
|
||||
* The mode for input devices available.
|
||||
*
|
||||
@ -991,8 +1046,8 @@ typedef enum
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_MODE_LOGICAL,
|
||||
CLUTTER_INPUT_MODE_PHYSICAL,
|
||||
CLUTTER_INPUT_MODE_MASTER,
|
||||
CLUTTER_INPUT_MODE_SLAVE,
|
||||
CLUTTER_INPUT_MODE_FLOATING
|
||||
} ClutterInputMode;
|
||||
|
||||
@ -1032,20 +1087,6 @@ typedef enum
|
||||
CLUTTER_INPUT_AXIS_LAST
|
||||
} ClutterInputAxis;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_AXIS_FLAG_NONE = 0,
|
||||
CLUTTER_INPUT_AXIS_FLAG_X = 1 << CLUTTER_INPUT_AXIS_X,
|
||||
CLUTTER_INPUT_AXIS_FLAG_Y = 1 << CLUTTER_INPUT_AXIS_Y,
|
||||
CLUTTER_INPUT_AXIS_FLAG_PRESSURE = 1 << CLUTTER_INPUT_AXIS_PRESSURE,
|
||||
CLUTTER_INPUT_AXIS_FLAG_XTILT = 1 << CLUTTER_INPUT_AXIS_XTILT,
|
||||
CLUTTER_INPUT_AXIS_FLAG_YTILT = 1 << CLUTTER_INPUT_AXIS_YTILT,
|
||||
CLUTTER_INPUT_AXIS_FLAG_WHEEL = 1 << CLUTTER_INPUT_AXIS_WHEEL,
|
||||
CLUTTER_INPUT_AXIS_FLAG_DISTANCE = 1 << CLUTTER_INPUT_AXIS_DISTANCE,
|
||||
CLUTTER_INPUT_AXIS_FLAG_ROTATION = 1 << CLUTTER_INPUT_AXIS_ROTATION,
|
||||
CLUTTER_INPUT_AXIS_FLAG_SLIDER = 1 << CLUTTER_INPUT_AXIS_SLIDER,
|
||||
} ClutterInputAxisFlags;
|
||||
|
||||
/**
|
||||
* ClutterSnapEdge:
|
||||
* @CLUTTER_SNAP_EDGE_TOP: the top edge
|
||||
@ -1159,7 +1200,7 @@ typedef enum /*< prefix=CLUTTER_TEXTURE >*/
|
||||
*
|
||||
* Since: 0.8
|
||||
*
|
||||
* Deprecated: 1.22: The #ClutterTexture class was the only user of
|
||||
* Deprecated: 1.22: The #ClutterTexture class was the only used ot
|
||||
* this API; use #ClutterImage and clutter_actor_set_content_scaling_filters()
|
||||
* instead.
|
||||
*/
|
||||
@ -1595,10 +1636,9 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_PAD_FEATURE_BUTTON,
|
||||
CLUTTER_PAD_FEATURE_RING,
|
||||
CLUTTER_PAD_FEATURE_STRIP,
|
||||
} ClutterInputDevicePadFeature;
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE,
|
||||
} ClutterInputDeviceMapping;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -1638,12 +1678,6 @@ typedef enum
|
||||
CLUTTER_INPUT_PANEL_STATE_TOGGLE,
|
||||
} ClutterInputPanelState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_PREEDIT_RESET_CLEAR,
|
||||
CLUTTER_PREEDIT_RESET_COMMIT,
|
||||
} ClutterPreeditResetMode;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ENUMS_H__ */
|
||||
|
@ -18,6 +18,7 @@ gboolean _clutter_event_process_filters (ClutterEvent *eve
|
||||
|
||||
/* clears the event queue inside the main context */
|
||||
void _clutter_clear_events_queue (void);
|
||||
void _clutter_clear_events_queue_for_stage (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_event_set_platform_data (ClutterEvent *event,
|
||||
|
@ -73,6 +73,8 @@ typedef struct _ClutterEventFilter {
|
||||
gpointer user_data;
|
||||
} ClutterEventFilter;
|
||||
|
||||
static GHashTable *all_events = NULL;
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterEvent, clutter_event,
|
||||
clutter_event_copy,
|
||||
clutter_event_free);
|
||||
@ -94,6 +96,15 @@ G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
|
||||
clutter_event_sequence_copy,
|
||||
clutter_event_sequence_free);
|
||||
|
||||
static gboolean
|
||||
is_event_allocated (const ClutterEvent *event)
|
||||
{
|
||||
if (all_events == NULL)
|
||||
return FALSE;
|
||||
|
||||
return g_hash_table_lookup (all_events, event) != NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_event_get_platform_data:
|
||||
* @event: a #ClutterEvent
|
||||
@ -107,6 +118,9 @@ G_DEFINE_BOXED_TYPE (ClutterEventSequence, clutter_event_sequence,
|
||||
gpointer
|
||||
_clutter_event_get_platform_data (const ClutterEvent *event)
|
||||
{
|
||||
if (!is_event_allocated (event))
|
||||
return NULL;
|
||||
|
||||
return ((ClutterEventPrivate *) event)->platform_data;
|
||||
}
|
||||
|
||||
@ -123,6 +137,9 @@ void
|
||||
_clutter_event_set_platform_data (ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
((ClutterEventPrivate *) event)->platform_data = data;
|
||||
}
|
||||
|
||||
@ -130,6 +147,9 @@ void
|
||||
_clutter_event_set_pointer_emulated (ClutterEvent *event,
|
||||
gboolean is_emulated)
|
||||
{
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
((ClutterEventPrivate *) event)->is_pointer_emulated = !!is_emulated;
|
||||
}
|
||||
|
||||
@ -384,6 +404,10 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
@ -391,11 +415,6 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
graphene_point_init (position, 0.f, 0.f);
|
||||
break;
|
||||
|
||||
@ -459,6 +478,10 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
@ -466,11 +489,6 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -697,6 +715,9 @@ clutter_event_set_scroll_delta (ClutterEvent *event,
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (event->type == CLUTTER_SCROLL);
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
event->scroll.direction = CLUTTER_SCROLL_SMOOTH;
|
||||
|
||||
((ClutterEventPrivate *) event)->delta_x = dx;
|
||||
@ -727,8 +748,13 @@ clutter_event_get_scroll_delta (const ClutterEvent *event,
|
||||
g_return_if_fail (event->type == CLUTTER_SCROLL);
|
||||
g_return_if_fail (event->scroll.direction == CLUTTER_SCROLL_SMOOTH);
|
||||
|
||||
delta_x = ((ClutterEventPrivate *) event)->delta_x;
|
||||
delta_y = ((ClutterEventPrivate *) event)->delta_y;
|
||||
delta_x = delta_y = 0;
|
||||
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
delta_x = ((ClutterEventPrivate *) event)->delta_x;
|
||||
delta_y = ((ClutterEventPrivate *) event)->delta_y;
|
||||
}
|
||||
|
||||
if (dx != NULL)
|
||||
*dx = delta_x;
|
||||
@ -1002,6 +1028,29 @@ clutter_event_get_event_sequence (const ClutterEvent *event)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_device_id:
|
||||
* @event: a clutter event
|
||||
*
|
||||
* Retrieves the events device id if set.
|
||||
*
|
||||
* Return value: A unique identifier for the device or -1 if the event has
|
||||
* no specific device set.
|
||||
*/
|
||||
gint
|
||||
clutter_event_get_device_id (const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = NULL;
|
||||
|
||||
g_return_val_if_fail (event != NULL, CLUTTER_POINTER_DEVICE);
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
return clutter_input_device_get_device_id (device);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_device_type:
|
||||
* @event: a #ClutterEvent
|
||||
@ -1040,20 +1089,24 @@ void
|
||||
clutter_event_set_device (ClutterEvent *event,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
g_set_object (&real_event->device, device);
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_set_object (&real_event->device, device);
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -1108,11 +1161,6 @@ clutter_event_set_device (ClutterEvent *event,
|
||||
case CLUTTER_PAD_RING:
|
||||
event->pad_ring.device = device;
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
event->device.device = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1137,19 +1185,24 @@ ClutterInputDevice *
|
||||
clutter_event_get_device (const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *device = NULL;
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
if (real_event->device != NULL)
|
||||
return real_event->device;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
if (real_event->device != NULL)
|
||||
return real_event->device;
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_EVENT_LAST:
|
||||
break;
|
||||
|
||||
@ -1205,11 +1258,6 @@ clutter_event_get_device (const ClutterEvent *event)
|
||||
case CLUTTER_PAD_RING:
|
||||
device = event->pad_ring.device;
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
device = event->device.device;
|
||||
break;
|
||||
}
|
||||
|
||||
return device;
|
||||
@ -1228,11 +1276,14 @@ void
|
||||
clutter_event_set_device_tool (ClutterEvent *event,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
real_event->tool = tool;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
real_event->tool = tool;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1248,11 +1299,16 @@ clutter_event_set_device_tool (ClutterEvent *event,
|
||||
ClutterInputDeviceTool *
|
||||
clutter_event_get_device_tool (const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
return real_event->tool;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
return real_event->tool;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1269,11 +1325,16 @@ clutter_event_new (ClutterEventType type)
|
||||
ClutterEvent *new_event;
|
||||
ClutterEventPrivate *priv;
|
||||
|
||||
priv = g_new0 (ClutterEventPrivate, 1);
|
||||
priv = g_slice_new0 (ClutterEventPrivate);
|
||||
|
||||
new_event = (ClutterEvent *) priv;
|
||||
new_event->type = new_event->any.type = type;
|
||||
|
||||
if (G_UNLIKELY (all_events == NULL))
|
||||
all_events = g_hash_table_new (NULL, NULL);
|
||||
|
||||
g_hash_table_replace (all_events, priv, GUINT_TO_POINTER (1));
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
@ -1290,7 +1351,8 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
{
|
||||
ClutterEvent *new_event;
|
||||
ClutterEventPrivate *new_real_event;
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
ClutterInputDevice *device;
|
||||
gint n_axes = 0;
|
||||
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
@ -1299,45 +1361,45 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
|
||||
*new_event = *event;
|
||||
|
||||
g_set_object (&new_real_event->device, real_event->device);
|
||||
g_set_object (&new_real_event->source_device, real_event->source_device);
|
||||
new_real_event->delta_x = real_event->delta_x;
|
||||
new_real_event->delta_y = real_event->delta_y;
|
||||
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
||||
new_real_event->base_state = real_event->base_state;
|
||||
new_real_event->button_state = real_event->button_state;
|
||||
new_real_event->latched_state = real_event->latched_state;
|
||||
new_real_event->locked_state = real_event->locked_state;
|
||||
new_real_event->tool = real_event->tool;
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_set_object (&new_real_event->device, real_event->device);
|
||||
g_set_object (&new_real_event->source_device, real_event->source_device);
|
||||
new_real_event->delta_x = real_event->delta_x;
|
||||
new_real_event->delta_y = real_event->delta_y;
|
||||
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
||||
new_real_event->base_state = real_event->base_state;
|
||||
new_real_event->button_state = real_event->button_state;
|
||||
new_real_event->latched_state = real_event->latched_state;
|
||||
new_real_event->locked_state = real_event->locked_state;
|
||||
new_real_event->tool = real_event->tool;
|
||||
}
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
n_axes = clutter_input_device_get_n_axes (device);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (event->button.axes != NULL)
|
||||
{
|
||||
new_event->button.axes =
|
||||
g_memdup2 (event->button.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->button.axes = g_memdup (event->button.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL:
|
||||
if (event->scroll.axes != NULL)
|
||||
{
|
||||
new_event->scroll.axes =
|
||||
g_memdup2 (event->scroll.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->scroll.axes = g_memdup (event->scroll.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
if (event->motion.axes != NULL)
|
||||
{
|
||||
new_event->motion.axes =
|
||||
g_memdup2 (event->motion.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
new_event->motion.axes = g_memdup (event->motion.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
@ -1345,26 +1407,19 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
case CLUTTER_TOUCH_END:
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
if (event->touch.axes != NULL)
|
||||
{
|
||||
new_event->touch.axes =
|
||||
g_memdup2 (event->touch.axes,
|
||||
sizeof (double) * CLUTTER_INPUT_AXIS_LAST);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
new_event->device.device = event->device.device;
|
||||
break;
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
new_event->im.text = g_strdup (event->im.text);
|
||||
new_event->touch.axes = g_memdup (event->touch.axes,
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_event_allocated (event))
|
||||
_clutter_backend_copy_event_data (clutter_get_default_backend (),
|
||||
event,
|
||||
new_event);
|
||||
|
||||
return new_event;
|
||||
}
|
||||
|
||||
@ -1379,10 +1434,15 @@ clutter_event_free (ClutterEvent *event)
|
||||
{
|
||||
if (G_LIKELY (event != NULL))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
|
||||
|
||||
g_clear_object (&real_event->device);
|
||||
g_clear_object (&real_event->source_device);
|
||||
if (is_event_allocated (event))
|
||||
{
|
||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
g_clear_object (&real_event->device);
|
||||
g_clear_object (&real_event->source_device);
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
@ -1406,16 +1466,12 @@ clutter_event_free (ClutterEvent *event)
|
||||
g_free (event->touch.axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
g_free (event->im.text);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_free ((ClutterEventPrivate *) event);
|
||||
g_hash_table_remove (all_events, event);
|
||||
g_slice_free (ClutterEventPrivate, (ClutterEventPrivate *) event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1433,11 +1489,40 @@ ClutterEvent *
|
||||
clutter_event_get (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterEvent *event;
|
||||
|
||||
event = g_async_queue_try_pop (context->events_queue);
|
||||
if (context->events_queue == NULL)
|
||||
return NULL;
|
||||
|
||||
return event;
|
||||
if (g_queue_is_empty (context->events_queue))
|
||||
return NULL;
|
||||
|
||||
return g_queue_pop_tail (context->events_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_peek:
|
||||
*
|
||||
* Returns a pointer to the first event from the event queue but
|
||||
* does not remove it.
|
||||
*
|
||||
* Return value: (transfer none): A #ClutterEvent or NULL if queue empty.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
ClutterEvent *
|
||||
clutter_event_peek (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
|
||||
g_return_val_if_fail (context != NULL, NULL);
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
return NULL;
|
||||
|
||||
if (g_queue_is_empty (context->events_queue))
|
||||
return NULL;
|
||||
|
||||
return g_queue_peek_tail (context->events_queue);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1445,9 +1530,21 @@ _clutter_event_push (const ClutterEvent *event,
|
||||
gboolean do_copy)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterInputDevice *device;
|
||||
|
||||
g_assert (context != NULL);
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
context->events_queue = g_queue_new ();
|
||||
|
||||
/* disabled devices don't propagate events */
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
{
|
||||
if (!clutter_input_device_get_enabled (device))
|
||||
return;
|
||||
}
|
||||
|
||||
if (do_copy)
|
||||
{
|
||||
ClutterEvent *copy;
|
||||
@ -1456,8 +1553,7 @@ _clutter_event_push (const ClutterEvent *event,
|
||||
event = copy;
|
||||
}
|
||||
|
||||
g_async_queue_push (context->events_queue, (gpointer) event);
|
||||
g_main_context_wakeup (NULL);
|
||||
g_queue_push_head (context->events_queue, (gpointer) event);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1494,7 +1590,10 @@ clutter_events_pending (void)
|
||||
|
||||
g_return_val_if_fail (context != NULL, FALSE);
|
||||
|
||||
return g_async_queue_length (context->events_queue) > 0;
|
||||
if (context->events_queue == NULL)
|
||||
return FALSE;
|
||||
|
||||
return g_queue_is_empty (context->events_queue) == FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1564,6 +1663,9 @@ clutter_event_get_source_device (const ClutterEvent *event)
|
||||
{
|
||||
ClutterEventPrivate *real_event;
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return NULL;
|
||||
|
||||
real_event = (ClutterEventPrivate *) event;
|
||||
|
||||
if (real_event->source_device != NULL)
|
||||
@ -1592,6 +1694,9 @@ clutter_event_set_source_device (ClutterEvent *event,
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (device == NULL || CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return;
|
||||
|
||||
real_event = (ClutterEventPrivate *) event;
|
||||
g_set_object (&real_event->source_device, device);
|
||||
}
|
||||
@ -1612,10 +1717,15 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
guint *n_axes)
|
||||
{
|
||||
gdouble *retval = NULL;
|
||||
guint len = 0;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_NOTHING:
|
||||
case CLUTTER_STAGE_STATE:
|
||||
case CLUTTER_DESTROY_NOTIFY:
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
case CLUTTER_DELETE:
|
||||
case CLUTTER_ENTER:
|
||||
case CLUTTER_LEAVE:
|
||||
case CLUTTER_KEY_PRESS:
|
||||
@ -1623,8 +1733,6 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL:
|
||||
@ -1653,14 +1761,22 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_IM_COMMIT:
|
||||
case CLUTTER_IM_DELETE:
|
||||
case CLUTTER_IM_PREEDIT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (retval != NULL)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
len = clutter_input_device_get_n_axes (device);
|
||||
else
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
if (n_axes)
|
||||
*n_axes = CLUTTER_INPUT_AXIS_LAST;
|
||||
*n_axes = len;
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -1779,6 +1895,9 @@ clutter_event_is_pointer_emulated (const ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
if (!is_event_allocated (event))
|
||||
return FALSE;
|
||||
|
||||
return ((ClutterEventPrivate *) event)->is_pointer_emulated;
|
||||
}
|
||||
|
||||
@ -1830,7 +1949,7 @@ clutter_event_add_filter (ClutterStage *stage,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterEventFilter *event_filter = g_new0 (ClutterEventFilter, 1);
|
||||
ClutterEventFilter *event_filter = g_slice_new (ClutterEventFilter);
|
||||
static guint event_filter_id = 0;
|
||||
|
||||
event_filter->stage = stage;
|
||||
@ -1871,7 +1990,7 @@ clutter_event_remove_filter (guint id)
|
||||
event_filter->notify (event_filter->user_data);
|
||||
|
||||
context->event_filters = g_list_delete_link (context->event_filters, l);
|
||||
g_free (event_filter);
|
||||
g_slice_free (ClutterEventFilter, event_filter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2007,42 +2126,6 @@ clutter_event_get_gesture_motion_delta (const ClutterEvent *event,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_gesture_motion_delta_unaccelerated:
|
||||
* @event: A clutter touchpad gesture event
|
||||
* @dx: (out) (allow-none): the displacement relative to the pointer
|
||||
* position in the X axis, or %NULL
|
||||
* @dy: (out) (allow-none): the displacement relative to the pointer
|
||||
* position in the Y axis, or %NULL
|
||||
*
|
||||
* Returns the unaccelerated gesture motion deltas relative to the current
|
||||
* pointer position. Unlike clutter_event_get_gesture_motion_delta(),
|
||||
* pointer acceleration is ignored.
|
||||
**/
|
||||
void
|
||||
clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
|
||||
gdouble *dx,
|
||||
gdouble *dy)
|
||||
{
|
||||
g_return_if_fail (event != NULL);
|
||||
g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
|
||||
event->type == CLUTTER_TOUCHPAD_SWIPE);
|
||||
|
||||
if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
||||
{
|
||||
if (dx)
|
||||
*dx = event->touchpad_pinch.dx_unaccel;
|
||||
if (dy)
|
||||
*dy = event->touchpad_pinch.dy_unaccel;
|
||||
}
|
||||
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
||||
{
|
||||
if (dx)
|
||||
*dx = event->touchpad_swipe.dx_unaccel;
|
||||
if (dy)
|
||||
*dy = event->touchpad_swipe.dy_unaccel;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* clutter_event_get_scroll_source:
|
||||
* @event: an scroll event
|
||||
@ -2163,58 +2246,3 @@ clutter_event_get_pad_event_details (const ClutterEvent *event,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
clutter_event_get_event_code (const ClutterEvent *event)
|
||||
{
|
||||
if (event->type == CLUTTER_KEY_PRESS ||
|
||||
event->type == CLUTTER_KEY_RELEASE)
|
||||
return event->key.evdev_code;
|
||||
else if (event->type == CLUTTER_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_BUTTON_RELEASE)
|
||||
return event->button.evdev_code;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
clutter_event_sequence_get_slot (const ClutterEventSequence *sequence)
|
||||
{
|
||||
g_return_val_if_fail (sequence != NULL, -1);
|
||||
|
||||
return GPOINTER_TO_INT (sequence) - 1;
|
||||
}
|
||||
|
||||
int64_t
|
||||
clutter_event_get_time_us (const ClutterEvent *event)
|
||||
{
|
||||
if (event->type == CLUTTER_MOTION)
|
||||
return event->motion.time_us;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_event_get_relative_motion (const ClutterEvent *event,
|
||||
double *dx,
|
||||
double *dy,
|
||||
double *dx_unaccel,
|
||||
double *dy_unaccel)
|
||||
{
|
||||
if (event->type == CLUTTER_MOTION &&
|
||||
event->motion.flags & CLUTTER_EVENT_FLAG_RELATIVE_MOTION)
|
||||
{
|
||||
if (dx)
|
||||
*dx = event->motion.dx;
|
||||
if (dy)
|
||||
*dy = event->motion.dy;
|
||||
if (dx_unaccel)
|
||||
*dx_unaccel = event->motion.dx_unaccel;
|
||||
if (dy_unaccel)
|
||||
*dy_unaccel = event->motion.dy_unaccel;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -112,6 +112,7 @@ typedef struct _ClutterButtonEvent ClutterButtonEvent;
|
||||
typedef struct _ClutterKeyEvent ClutterKeyEvent;
|
||||
typedef struct _ClutterMotionEvent ClutterMotionEvent;
|
||||
typedef struct _ClutterScrollEvent ClutterScrollEvent;
|
||||
typedef struct _ClutterStageStateEvent ClutterStageStateEvent;
|
||||
typedef struct _ClutterCrossingEvent ClutterCrossingEvent;
|
||||
typedef struct _ClutterTouchEvent ClutterTouchEvent;
|
||||
typedef struct _ClutterTouchpadPinchEvent ClutterTouchpadPinchEvent;
|
||||
@ -120,8 +121,6 @@ typedef struct _ClutterProximityEvent ClutterProximityEvent;
|
||||
typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent;
|
||||
typedef struct _ClutterPadStripEvent ClutterPadStripEvent;
|
||||
typedef struct _ClutterPadRingEvent ClutterPadRingEvent;
|
||||
typedef struct _ClutterDeviceEvent ClutterDeviceEvent;
|
||||
typedef struct _ClutterIMEvent ClutterIMEvent;
|
||||
|
||||
/**
|
||||
* ClutterAnyEvent:
|
||||
@ -173,7 +172,6 @@ struct _ClutterKeyEvent
|
||||
guint keyval;
|
||||
guint16 hardware_keycode;
|
||||
gunichar unicode_value;
|
||||
uint32_t evdev_code;
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
@ -217,7 +215,6 @@ struct _ClutterButtonEvent
|
||||
guint click_count;
|
||||
gdouble *axes; /* Future use */
|
||||
ClutterInputDevice *device;
|
||||
uint32_t evdev_code;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -307,12 +304,6 @@ struct _ClutterMotionEvent
|
||||
ClutterModifierType modifier_state;
|
||||
gdouble *axes; /* Future use */
|
||||
ClutterInputDevice *device;
|
||||
|
||||
int64_t time_us;
|
||||
double dx;
|
||||
double dy;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -354,6 +345,32 @@ struct _ClutterScrollEvent
|
||||
ClutterScrollFinishFlags finish_flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterStageStateEvent:
|
||||
* @type: event type
|
||||
* @time: event time
|
||||
* @flags: event flags
|
||||
* @stage: event source stage
|
||||
* @source: event source actor (unused)
|
||||
* @changed_mask: bitwise OR of the changed flags
|
||||
* @new_state: bitwise OR of the current state flags
|
||||
*
|
||||
* Event signalling a change in the #ClutterStage state.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
struct _ClutterStageStateEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source; /* XXX: should probably be the stage itself */
|
||||
|
||||
ClutterStageState changed_mask;
|
||||
ClutterStageState new_state;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterTouchEvent:
|
||||
* @type: event type
|
||||
@ -414,10 +431,6 @@ struct _ClutterTouchEvent
|
||||
* @y: the Y coordinate of the pointer, relative to the stage
|
||||
* @dx: movement delta of the pinch focal point in the X axis
|
||||
* @dy: movement delta of the pinch focal point in the Y axis
|
||||
* @dx_unaccel: unaccelerated movement delta of the pinch focal
|
||||
* point in the X axis
|
||||
* @dy_unaccel: unaccelerated movement delta of the pinch focal
|
||||
* point in the Y axis
|
||||
* @angle_delta: angle delta in degrees, clockwise rotations are
|
||||
* represented by positive deltas
|
||||
* @scale: the current scale
|
||||
@ -445,8 +458,6 @@ struct _ClutterTouchpadPinchEvent
|
||||
gfloat y;
|
||||
gfloat dx;
|
||||
gfloat dy;
|
||||
gfloat dx_unaccel;
|
||||
gfloat dy_unaccel;
|
||||
gfloat angle_delta;
|
||||
gfloat scale;
|
||||
guint n_fingers;
|
||||
@ -463,12 +474,8 @@ struct _ClutterTouchpadPinchEvent
|
||||
* @n_fingers: the number of fingers triggering the swipe
|
||||
* @x: the X coordinate of the pointer, relative to the stage
|
||||
* @y: the Y coordinate of the pointer, relative to the stage
|
||||
* @dx: movement delta of the swipe center point in the X axis
|
||||
* @dy: movement delta of the swipe center point in the Y axis
|
||||
* @dx_unaccel: unaccelerated movement delta of the swipe center
|
||||
* point in the X axis
|
||||
* @dy_unaccel: unaccelerated movement delta of the swipe center
|
||||
* point in the Y axis
|
||||
* @dx: movement delta of the pinch focal point in the X axis
|
||||
* @dy: movement delta of the pinch focal point in the Y axis
|
||||
*
|
||||
* Used for touchpad swipe gesture events. The current state of the
|
||||
* gesture will be determined by the @phase field.
|
||||
@ -489,8 +496,6 @@ struct _ClutterTouchpadSwipeEvent
|
||||
gfloat y;
|
||||
gfloat dx;
|
||||
gfloat dy;
|
||||
gfloat dx_unaccel;
|
||||
gfloat dy_unaccel;
|
||||
};
|
||||
|
||||
struct _ClutterPadButtonEvent
|
||||
@ -539,31 +544,6 @@ struct _ClutterPadRingEvent
|
||||
guint32 mode;
|
||||
};
|
||||
|
||||
struct _ClutterDeviceEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
struct _ClutterIMEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
uint32_t time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
char *text;
|
||||
int32_t offset;
|
||||
uint32_t len;
|
||||
ClutterPreeditResetMode mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterEvent:
|
||||
*
|
||||
@ -581,6 +561,7 @@ union _ClutterEvent
|
||||
ClutterKeyEvent key;
|
||||
ClutterMotionEvent motion;
|
||||
ClutterScrollEvent scroll;
|
||||
ClutterStageStateEvent stage_state;
|
||||
ClutterCrossingEvent crossing;
|
||||
ClutterTouchEvent touch;
|
||||
ClutterTouchpadPinchEvent touchpad_pinch;
|
||||
@ -589,8 +570,6 @@ union _ClutterEvent
|
||||
ClutterPadButtonEvent pad_button;
|
||||
ClutterPadStripEvent pad_strip;
|
||||
ClutterPadRingEvent pad_ring;
|
||||
ClutterDeviceEvent device;
|
||||
ClutterIMEvent im;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -622,6 +601,8 @@ gboolean clutter_events_pending (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterEvent * clutter_event_get (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterEvent * clutter_event_peek (void);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_event_put (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
@ -692,6 +673,8 @@ void clutter_event_set_stage (ClutterEvent
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * clutter_event_get_stage (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_event_get_device_id (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceType clutter_event_get_device_type (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_event_set_coords (ClutterEvent *event,
|
||||
@ -790,11 +773,6 @@ void clutter_event_get_gesture_motion_delta (const Clut
|
||||
gdouble *dx,
|
||||
gdouble *dy);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
|
||||
gdouble *dx,
|
||||
gdouble *dy);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event);
|
||||
|
||||
@ -809,20 +787,6 @@ gboolean clutter_event_get_pad_event_details (const Clut
|
||||
guint *number,
|
||||
guint *mode,
|
||||
gdouble *value);
|
||||
CLUTTER_EXPORT
|
||||
uint32_t clutter_event_get_event_code (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
int32_t clutter_event_sequence_get_slot (const ClutterEventSequence *sequence);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
int64_t clutter_event_get_time_us (const ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_event_get_relative_motion (const ClutterEvent *event,
|
||||
double *dx,
|
||||
double *dy,
|
||||
double *dx_unaccel,
|
||||
double *dy_unaccel);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -139,11 +139,7 @@ clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
|
||||
child != NULL;
|
||||
child = clutter_actor_get_next_sibling (child))
|
||||
{
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
clutter_actor_get_fixed_position (child, &x, &y);
|
||||
clutter_actor_allocate_preferred_size (child, x, y);
|
||||
clutter_actor_allocate_preferred_size (child);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,7 +913,7 @@ clutter_flow_layout_class_init (ClutterFlowLayoutClass *klass)
|
||||
* ClutterFlowLayout:orientation:
|
||||
*
|
||||
* The orientation of the #ClutterFlowLayout. The children
|
||||
* of the layout will be laid out following the orientation.
|
||||
* of the layout will be layed out following the orientation.
|
||||
*
|
||||
* This property also controls the overflowing directions
|
||||
*
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "clutter/clutter-frame-clock.h"
|
||||
|
||||
#include "clutter/clutter-debug.h"
|
||||
#include "clutter/clutter-main.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-timeline-private.h"
|
||||
@ -34,21 +33,8 @@ enum
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
/* An estimate queue holds several int64_t values. Adding a new value to the
|
||||
* queue overwrites the oldest value.
|
||||
*/
|
||||
#define ESTIMATE_QUEUE_LENGTH 16
|
||||
|
||||
typedef struct _EstimateQueue
|
||||
{
|
||||
int64_t values[ESTIMATE_QUEUE_LENGTH];
|
||||
int next_index;
|
||||
} EstimateQueue;
|
||||
|
||||
/* When heuristic render time is off,
|
||||
* wait 2ms after vblank before starting to draw next frame.
|
||||
*/
|
||||
#define SYNC_DELAY_FALLBACK_US ms2us (2)
|
||||
/* Wait 2ms after vblank before starting to draw next frame */
|
||||
#define SYNC_DELAY_US ms2us (2)
|
||||
|
||||
typedef struct _ClutterFrameListener
|
||||
{
|
||||
@ -77,7 +63,6 @@ struct _ClutterFrameClock
|
||||
GObject parent;
|
||||
|
||||
float refresh_rate;
|
||||
int64_t refresh_interval_us;
|
||||
ClutterFrameListener listener;
|
||||
|
||||
GSource *source;
|
||||
@ -85,29 +70,11 @@ struct _ClutterFrameClock
|
||||
int64_t frame_count;
|
||||
|
||||
ClutterFrameClockState state;
|
||||
int64_t last_dispatch_time_us;
|
||||
int64_t last_dispatch_lateness_us;
|
||||
int64_t last_presentation_time_us;
|
||||
|
||||
gboolean is_next_presentation_time_valid;
|
||||
int64_t next_presentation_time_us;
|
||||
|
||||
/* Buffer must be submitted to KMS and GPU rendering must be finished
|
||||
* this amount of time before the next presentation time.
|
||||
*/
|
||||
int64_t vblank_duration_us;
|
||||
/* Last KMS buffer submission time. */
|
||||
int64_t last_flip_time_us;
|
||||
|
||||
/* Last few durations between dispatch start and buffer swap. */
|
||||
EstimateQueue dispatch_to_swap_us;
|
||||
/* Last few durations between buffer swap and GPU rendering finish. */
|
||||
EstimateQueue swap_to_rendering_done_us;
|
||||
/* Last few durations between buffer swap and KMS submission. */
|
||||
EstimateQueue swap_to_flip_us;
|
||||
/* If we got new measurements last frame. */
|
||||
gboolean got_measurements_last_frame;
|
||||
|
||||
gboolean pending_reschedule;
|
||||
gboolean pending_reschedule_now;
|
||||
|
||||
@ -119,29 +86,12 @@ struct _ClutterFrameClock
|
||||
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
estimate_queue_add_value (EstimateQueue *queue,
|
||||
int64_t value)
|
||||
{
|
||||
queue->values[queue->next_index] = value;
|
||||
queue->next_index = (queue->next_index + 1) % ESTIMATE_QUEUE_LENGTH;
|
||||
}
|
||||
|
||||
float
|
||||
clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
return frame_clock->refresh_rate;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_frame_clock_set_refresh_rate (ClutterFrameClock *frame_clock,
|
||||
float refresh_rate)
|
||||
{
|
||||
frame_clock->refresh_rate = refresh_rate;
|
||||
frame_clock->refresh_interval_us =
|
||||
(int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
|
||||
ClutterTimeline *timeline)
|
||||
@ -231,44 +181,20 @@ void
|
||||
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
ClutterFrameInfo *frame_info)
|
||||
{
|
||||
frame_clock->last_presentation_time_us = frame_info->presentation_time;
|
||||
int64_t presentation_time_us = frame_info->presentation_time;
|
||||
|
||||
frame_clock->got_measurements_last_frame = FALSE;
|
||||
|
||||
if (frame_info->cpu_time_before_buffer_swap_us != 0 &&
|
||||
frame_info->gpu_rendering_duration_ns != 0)
|
||||
if (presentation_time_us > frame_clock->last_presentation_time_us ||
|
||||
((presentation_time_us - frame_clock->last_presentation_time_us) >
|
||||
INT64_MAX / 2))
|
||||
{
|
||||
int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us;
|
||||
|
||||
dispatch_to_swap_us =
|
||||
frame_info->cpu_time_before_buffer_swap_us -
|
||||
frame_clock->last_dispatch_time_us;
|
||||
swap_to_rendering_done_us =
|
||||
frame_info->gpu_rendering_duration_ns / 1000;
|
||||
swap_to_flip_us =
|
||||
frame_clock->last_flip_time_us -
|
||||
frame_info->cpu_time_before_buffer_swap_us;
|
||||
|
||||
CLUTTER_NOTE (FRAME_TIMINGS,
|
||||
"dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
|
||||
dispatch_to_swap_us,
|
||||
swap_to_rendering_done_us,
|
||||
swap_to_flip_us);
|
||||
|
||||
estimate_queue_add_value (&frame_clock->dispatch_to_swap_us,
|
||||
dispatch_to_swap_us);
|
||||
estimate_queue_add_value (&frame_clock->swap_to_rendering_done_us,
|
||||
swap_to_rendering_done_us);
|
||||
estimate_queue_add_value (&frame_clock->swap_to_flip_us,
|
||||
swap_to_flip_us);
|
||||
|
||||
frame_clock->got_measurements_last_frame = TRUE;
|
||||
frame_clock->last_presentation_time_us = presentation_time_us;
|
||||
}
|
||||
|
||||
if (frame_info->refresh_rate > 1)
|
||||
else
|
||||
{
|
||||
clutter_frame_clock_set_refresh_rate (frame_clock,
|
||||
frame_info->refresh_rate);
|
||||
g_warning_once ("Bogus presentation time %" G_GINT64_FORMAT
|
||||
" travelled back in time, using current time.",
|
||||
presentation_time_us);
|
||||
frame_clock->last_presentation_time_us = g_get_monotonic_time ();
|
||||
}
|
||||
|
||||
switch (frame_clock->state)
|
||||
@ -286,76 +212,6 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
g_warn_if_reached ();
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||
maybe_reschedule_update (frame_clock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int64_t
|
||||
clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
int64_t refresh_interval_us;
|
||||
int64_t max_dispatch_to_swap_us = 0;
|
||||
int64_t max_swap_to_rendering_done_us = 0;
|
||||
int64_t max_swap_to_flip_us = 0;
|
||||
int64_t max_render_time_us;
|
||||
int i;
|
||||
|
||||
refresh_interval_us =
|
||||
(int64_t) (0.5 + G_USEC_PER_SEC / frame_clock->refresh_rate);
|
||||
|
||||
if (!frame_clock->got_measurements_last_frame ||
|
||||
G_UNLIKELY (clutter_paint_debug_flags &
|
||||
CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME))
|
||||
return refresh_interval_us - SYNC_DELAY_FALLBACK_US;
|
||||
|
||||
for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i)
|
||||
{
|
||||
max_dispatch_to_swap_us =
|
||||
MAX (max_dispatch_to_swap_us,
|
||||
frame_clock->dispatch_to_swap_us.values[i]);
|
||||
max_swap_to_rendering_done_us =
|
||||
MAX (max_swap_to_rendering_done_us,
|
||||
frame_clock->swap_to_rendering_done_us.values[i]);
|
||||
max_swap_to_flip_us =
|
||||
MAX (max_swap_to_flip_us,
|
||||
frame_clock->swap_to_flip_us.values[i]);
|
||||
}
|
||||
|
||||
/* Max render time shows how early the frame clock needs to be dispatched
|
||||
* to make it to the predicted next presentation time. It is composed of:
|
||||
* - An estimate of duration from dispatch start to buffer swap.
|
||||
* - Maximum between estimates of duration from buffer swap to GPU rendering
|
||||
* finish and duration from buffer swap to buffer submission to KMS. This
|
||||
* is because both of these things need to happen before the vblank, and
|
||||
* they are done in parallel.
|
||||
* - Duration of the vblank.
|
||||
* - A constant to account for variations in the above estimates.
|
||||
*/
|
||||
max_render_time_us =
|
||||
max_dispatch_to_swap_us +
|
||||
MAX (max_swap_to_rendering_done_us, max_swap_to_flip_us) +
|
||||
frame_clock->vblank_duration_us +
|
||||
clutter_max_render_time_constant_us;
|
||||
|
||||
max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us);
|
||||
|
||||
return max_render_time_us;
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
int64_t *out_next_update_time_us,
|
||||
@ -363,6 +219,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
{
|
||||
int64_t last_presentation_time_us;
|
||||
int64_t now_us;
|
||||
float refresh_rate;
|
||||
int64_t refresh_interval_us;
|
||||
int64_t min_render_time_allowed_us;
|
||||
int64_t max_render_time_allowed_us;
|
||||
@ -373,119 +230,36 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
|
||||
now_us = g_get_monotonic_time ();
|
||||
|
||||
refresh_interval_us = frame_clock->refresh_interval_us;
|
||||
|
||||
if (frame_clock->last_presentation_time_us == 0)
|
||||
{
|
||||
*out_next_update_time_us =
|
||||
frame_clock->last_dispatch_time_us ?
|
||||
((frame_clock->last_dispatch_time_us -
|
||||
frame_clock->last_dispatch_lateness_us) + refresh_interval_us) :
|
||||
now_us;
|
||||
|
||||
*out_next_presentation_time_us = 0;
|
||||
return;
|
||||
}
|
||||
refresh_rate = frame_clock->refresh_rate;
|
||||
refresh_interval_us = (int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
|
||||
|
||||
min_render_time_allowed_us = refresh_interval_us / 2;
|
||||
max_render_time_allowed_us =
|
||||
clutter_frame_clock_compute_max_render_time_us (frame_clock);
|
||||
max_render_time_allowed_us = refresh_interval_us - SYNC_DELAY_US;
|
||||
|
||||
if (min_render_time_allowed_us > max_render_time_allowed_us)
|
||||
min_render_time_allowed_us = max_render_time_allowed_us;
|
||||
|
||||
/*
|
||||
* The common case is that the next presentation happens 1 refresh interval
|
||||
* after the last presentation:
|
||||
*
|
||||
* last_presentation_time_us
|
||||
* / next_presentation_time_us
|
||||
* / /
|
||||
* / /
|
||||
* |--|--o----|-------|--> presentation times
|
||||
* | | \ |
|
||||
* | | now_us
|
||||
* | \______/
|
||||
* | refresh_interval_us
|
||||
* |
|
||||
* 0
|
||||
*
|
||||
*/
|
||||
last_presentation_time_us = frame_clock->last_presentation_time_us;
|
||||
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
|
||||
|
||||
/*
|
||||
* However, the last presentation could have happened more than a frame ago.
|
||||
* For example, due to idling (nothing on screen changed, so no need to
|
||||
* redraw) or due to frames missing deadlines (GPU busy with heavy rendering).
|
||||
* The following code adjusts next_presentation_time_us to be in the future,
|
||||
* but still aligned to display presentation times. Instead of
|
||||
* next presentation = last presentation + 1 * refresh interval, it will be
|
||||
* next presentation = last presentation + N * refresh interval.
|
||||
*/
|
||||
/* Skip ahead to get close to the actual next presentation time. */
|
||||
if (next_presentation_time_us < now_us)
|
||||
{
|
||||
int64_t presentation_phase_us;
|
||||
int64_t current_phase_us;
|
||||
int64_t current_refresh_interval_start_us;
|
||||
int64_t logical_clock_offset_us;
|
||||
int64_t logical_clock_phase_us;
|
||||
int64_t hw_clock_offset_us;
|
||||
|
||||
/*
|
||||
* Let's say we're just past next_presentation_time_us.
|
||||
*
|
||||
* First, we compute presentation_phase_us. Real presentation times don't
|
||||
* have to be exact multiples of refresh_interval_us and
|
||||
* presentation_phase_us represents this difference. Next, we compute
|
||||
* current phase and the refresh interval start corresponding to now_us.
|
||||
* Finally, add presentation_phase_us and a refresh interval to get the
|
||||
* next presentation after now_us.
|
||||
*
|
||||
* last_presentation_time_us
|
||||
* / next_presentation_time_us
|
||||
* / / now_us
|
||||
* / / / new next_presentation_time_us
|
||||
* |--|-------|---o---|-------|--> presentation times
|
||||
* | __|
|
||||
* | |presentation_phase_us
|
||||
* | |
|
||||
* | | now_us - presentation_phase_us
|
||||
* | | /
|
||||
* |-------|---o---|-------|-----> integer multiples of refresh_interval_us
|
||||
* | \__/
|
||||
* | |current_phase_us
|
||||
* | \
|
||||
* | current_refresh_interval_start_us
|
||||
* 0
|
||||
*
|
||||
*/
|
||||
logical_clock_offset_us = now_us % refresh_interval_us;
|
||||
logical_clock_phase_us = now_us - logical_clock_offset_us;
|
||||
hw_clock_offset_us = last_presentation_time_us % refresh_interval_us;
|
||||
|
||||
presentation_phase_us = last_presentation_time_us % refresh_interval_us;
|
||||
current_phase_us = (now_us - presentation_phase_us) % refresh_interval_us;
|
||||
current_refresh_interval_start_us =
|
||||
now_us - presentation_phase_us - current_phase_us;
|
||||
|
||||
next_presentation_time_us =
|
||||
current_refresh_interval_start_us +
|
||||
presentation_phase_us +
|
||||
refresh_interval_us;
|
||||
next_presentation_time_us = logical_clock_phase_us + hw_clock_offset_us;
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip one interval if we got an early presented event.
|
||||
*
|
||||
* last frame this was last_presentation_time
|
||||
* / frame_clock->next_presentation_time_us
|
||||
* / /
|
||||
* |---|-o-----|-x----->
|
||||
* | \
|
||||
* \ next_presentation_time_us is thus right after the last one
|
||||
* but got an unexpected early presentation
|
||||
* \_/
|
||||
* time_since_last_next_presentation_time_us
|
||||
*
|
||||
*/
|
||||
/* Skip one interval if we got an early presented event. */
|
||||
last_next_presentation_time_us = frame_clock->next_presentation_time_us;
|
||||
time_since_last_next_presentation_time_us =
|
||||
next_presentation_time_us - last_next_presentation_time_us;
|
||||
next_presentation_time_us - last_next_presentation_time_us;
|
||||
if (frame_clock->is_next_presentation_time_valid &&
|
||||
time_since_last_next_presentation_time_us < (refresh_interval_us / 2))
|
||||
{
|
||||
@ -592,8 +366,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
||||
calculate_next_update_time_us (frame_clock,
|
||||
&next_update_time_us,
|
||||
&frame_clock->next_presentation_time_us);
|
||||
frame_clock->is_next_presentation_time_valid =
|
||||
(frame_clock->next_presentation_time_us != 0);
|
||||
frame_clock->is_next_presentation_time_valid = TRUE;
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
return;
|
||||
@ -615,21 +388,9 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
||||
{
|
||||
int64_t frame_count;
|
||||
ClutterFrameResult result;
|
||||
int64_t ideal_dispatch_time_us, lateness_us;
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockDispatch, "Frame Clock (dispatch)");
|
||||
COGL_TRACE_BEGIN_SCOPED (ClutterFrameCLockDispatch, "Frame Clock (dispatch)");
|
||||
|
||||
ideal_dispatch_time_us = (frame_clock->last_dispatch_time_us -
|
||||
frame_clock->last_dispatch_lateness_us) +
|
||||
frame_clock->refresh_interval_us;
|
||||
|
||||
lateness_us = time_us - ideal_dispatch_time_us;
|
||||
if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us)
|
||||
frame_clock->last_dispatch_lateness_us = 0;
|
||||
else
|
||||
frame_clock->last_dispatch_lateness_us = lateness_us;
|
||||
|
||||
frame_clock->last_dispatch_time_us = time_us;
|
||||
g_source_set_ready_time (frame_clock->source, -1);
|
||||
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
|
||||
@ -695,58 +456,6 @@ frame_clock_source_dispatch (GSource *source,
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
||||
int64_t flip_time_us)
|
||||
{
|
||||
frame_clock->last_flip_time_us = flip_time_us;
|
||||
}
|
||||
|
||||
GString *
|
||||
clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
int64_t max_dispatch_to_swap_us = 0;
|
||||
int64_t max_swap_to_rendering_done_us = 0;
|
||||
int64_t max_swap_to_flip_us = 0;
|
||||
int i;
|
||||
GString *string;
|
||||
|
||||
string = g_string_new (NULL);
|
||||
g_string_append_printf (string, "Max render time: %ld µs",
|
||||
clutter_frame_clock_compute_max_render_time_us (frame_clock));
|
||||
|
||||
if (frame_clock->got_measurements_last_frame)
|
||||
g_string_append_printf (string, " =");
|
||||
else
|
||||
g_string_append_printf (string, " (no measurements last frame)");
|
||||
|
||||
for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i)
|
||||
{
|
||||
max_dispatch_to_swap_us =
|
||||
MAX (max_dispatch_to_swap_us,
|
||||
frame_clock->dispatch_to_swap_us.values[i]);
|
||||
max_swap_to_rendering_done_us =
|
||||
MAX (max_swap_to_rendering_done_us,
|
||||
frame_clock->swap_to_rendering_done_us.values[i]);
|
||||
max_swap_to_flip_us =
|
||||
MAX (max_swap_to_flip_us,
|
||||
frame_clock->swap_to_flip_us.values[i]);
|
||||
}
|
||||
|
||||
g_string_append_printf (string, "\nVblank duration: %ld µs +",
|
||||
frame_clock->vblank_duration_us);
|
||||
g_string_append_printf (string, "\nDispatch to swap: %ld µs +",
|
||||
max_dispatch_to_swap_us);
|
||||
g_string_append_printf (string, "\nmax(Swap to rendering done: %ld µs,",
|
||||
max_swap_to_rendering_done_us);
|
||||
g_string_append_printf (string, "\nSwap to flip: %ld µs) +",
|
||||
max_swap_to_flip_us);
|
||||
g_string_append_printf (string, "\nConstant: %d µs",
|
||||
clutter_max_render_time_constant_us);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static GSourceFuncs frame_clock_source_funcs = {
|
||||
NULL,
|
||||
NULL,
|
||||
@ -776,7 +485,6 @@ init_frame_clock_source (ClutterFrameClock *frame_clock)
|
||||
|
||||
ClutterFrameClock *
|
||||
clutter_frame_clock_new (float refresh_rate,
|
||||
int64_t vblank_duration_us,
|
||||
const ClutterFrameListenerIface *iface,
|
||||
gpointer user_data)
|
||||
{
|
||||
@ -791,8 +499,7 @@ clutter_frame_clock_new (float refresh_rate,
|
||||
|
||||
init_frame_clock_source (frame_clock);
|
||||
|
||||
clutter_frame_clock_set_refresh_rate (frame_clock, refresh_rate);
|
||||
frame_clock->vblank_duration_us = vblank_duration_us;
|
||||
frame_clock->refresh_rate = refresh_rate;
|
||||
|
||||
return frame_clock;
|
||||
}
|
||||
@ -807,7 +514,7 @@ clutter_frame_clock_destroy (ClutterFrameClock *frame_clock)
|
||||
static void
|
||||
clutter_frame_clock_dispose (GObject *object)
|
||||
{
|
||||
ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object);
|
||||
ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object);
|
||||
|
||||
if (frame_clock->source)
|
||||
{
|
||||
|
@ -40,9 +40,6 @@ G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||
CLUTTER, FRAME_CLOCK,
|
||||
GObject)
|
||||
|
||||
/**
|
||||
* ClutterFrameListenerIface: (skip)
|
||||
*/
|
||||
typedef struct _ClutterFrameListenerIface
|
||||
{
|
||||
void (* before_frame) (ClutterFrameClock *frame_clock,
|
||||
@ -56,7 +53,6 @@ typedef struct _ClutterFrameListenerIface
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_frame_clock_new (float refresh_rate,
|
||||
int64_t vblank_duration_us,
|
||||
const ClutterFrameListenerIface *iface,
|
||||
gpointer user_data);
|
||||
|
||||
@ -67,9 +63,6 @@ CLUTTER_EXPORT
|
||||
void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
|
||||
|
||||
@ -91,9 +84,4 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
||||
CLUTTER_EXPORT
|
||||
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
|
||||
|
||||
void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
||||
int64_t flip_time_us);
|
||||
|
||||
GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock);
|
||||
|
||||
#endif /* CLUTTER_FRAME_CLOCK_H */
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_FRAME_PRIVATE_H
|
||||
#define CLUTTER_FRAME_PRIVATE_H
|
||||
|
||||
#include "clutter/clutter-frame.h"
|
||||
|
||||
struct _ClutterFrame
|
||||
{
|
||||
gboolean has_result;
|
||||
ClutterFrameResult result;
|
||||
};
|
||||
|
||||
#define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 })
|
||||
|
||||
ClutterFrameResult clutter_frame_get_result (ClutterFrame *frame);
|
||||
|
||||
#endif /* CLUTTER_FRAME_PRIVATE_H */
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter/clutter-frame-private.h"
|
||||
|
||||
ClutterFrameResult
|
||||
clutter_frame_get_result (ClutterFrame *frame)
|
||||
{
|
||||
g_return_val_if_fail (frame->has_result, CLUTTER_FRAME_RESULT_IDLE);
|
||||
|
||||
return frame->result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_frame_has_result (ClutterFrame *frame)
|
||||
{
|
||||
return frame->has_result;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_set_result (ClutterFrame *frame,
|
||||
ClutterFrameResult result)
|
||||
{
|
||||
g_warn_if_fail (!frame->has_result);
|
||||
|
||||
frame->result = result;
|
||||
frame->has_result = TRUE;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_FRAME_H
|
||||
#define CLUTTER_FRAME_H
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include "clutter/clutter-frame-clock.h"
|
||||
|
||||
typedef struct _ClutterFrame ClutterFrame;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_set_result (ClutterFrame *frame,
|
||||
ClutterFrameResult result);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_frame_has_result (ClutterFrame *frame);
|
||||
|
||||
#endif /* CLUTTER_FRAME_H */
|
@ -416,10 +416,12 @@ stage_captured_event_cb (ClutterActor *stage,
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
gesture_update_motion_point (point, event);
|
||||
|
||||
if (!begin_gesture (action, actor))
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
{
|
||||
if ((point = gesture_find_point (action, event, &position)) != NULL)
|
||||
gesture_update_motion_point (point, event);
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
|
||||
if ((point = gesture_find_point (action, event, &position)) == NULL)
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
@ -572,13 +574,8 @@ clutter_gesture_action_set_enabled (ClutterActorMeta *meta,
|
||||
ClutterGestureActionPrivate *priv =
|
||||
clutter_gesture_action_get_instance_private (gesture_action);
|
||||
|
||||
if (!is_enabled)
|
||||
{
|
||||
if (priv->in_gesture)
|
||||
cancel_gesture (gesture_action);
|
||||
else
|
||||
g_array_set_size (priv->points, 0);
|
||||
}
|
||||
if (!is_enabled && priv->in_gesture)
|
||||
cancel_gesture (gesture_action);
|
||||
|
||||
meta_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
|
@ -29,23 +29,6 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-types.h"
|
||||
|
||||
static gboolean
|
||||
graphene_matrix_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
double progress,
|
||||
GValue *retval)
|
||||
{
|
||||
const graphene_matrix_t *am = g_value_get_boxed (a);
|
||||
const graphene_matrix_t *bm = g_value_get_boxed (b);
|
||||
graphene_matrix_t res;
|
||||
|
||||
graphene_matrix_interpolate (am, bm, progress, &res);
|
||||
|
||||
g_value_set_boxed (retval, &res);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
graphene_point_progress (const GValue *a,
|
||||
const GValue *b,
|
||||
@ -117,8 +100,6 @@ graphene_size_progress (const GValue *a,
|
||||
void
|
||||
clutter_graphene_init (void)
|
||||
{
|
||||
clutter_interval_register_progress_func (GRAPHENE_TYPE_MATRIX,
|
||||
graphene_matrix_progress);
|
||||
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT,
|
||||
graphene_point_progress);
|
||||
clutter_interval_register_progress_func (GRAPHENE_TYPE_POINT3D,
|
||||
|
@ -44,7 +44,7 @@ _clutter_id_pool_new (guint initial_size)
|
||||
{
|
||||
ClutterIDPool *self;
|
||||
|
||||
self = g_new0 (ClutterIDPool, 1);
|
||||
self = g_slice_new (ClutterIDPool);
|
||||
|
||||
self->array = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (gpointer), initial_size);
|
||||
@ -59,7 +59,7 @@ _clutter_id_pool_free (ClutterIDPool *id_pool)
|
||||
|
||||
g_array_free (id_pool->array, TRUE);
|
||||
g_slist_free (id_pool->free_ids);
|
||||
g_free (id_pool);
|
||||
g_slice_free (ClutterIDPool, id_pool);
|
||||
}
|
||||
|
||||
guint32
|
||||
|
@ -38,6 +38,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-image.h"
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
|
@ -32,6 +32,44 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterAxisInfo
|
||||
{
|
||||
ClutterInputAxis axis;
|
||||
|
||||
double min_axis;
|
||||
double max_axis;
|
||||
|
||||
double min_value;
|
||||
double max_value;
|
||||
|
||||
double resolution;
|
||||
} ClutterAxisInfo;
|
||||
|
||||
typedef struct _ClutterKeyInfo
|
||||
{
|
||||
guint keyval;
|
||||
ClutterModifierType modifiers;
|
||||
} ClutterKeyInfo;
|
||||
|
||||
typedef struct _ClutterScrollInfo
|
||||
{
|
||||
guint axis_id;
|
||||
ClutterScrollDirection direction;
|
||||
double increment;
|
||||
|
||||
double last_value;
|
||||
guint last_value_valid : 1;
|
||||
} ClutterScrollInfo;
|
||||
|
||||
typedef struct _ClutterTouchInfo
|
||||
{
|
||||
ClutterEventSequence *sequence;
|
||||
ClutterActor *actor;
|
||||
|
||||
float current_x;
|
||||
float current_y;
|
||||
} ClutterTouchInfo;
|
||||
|
||||
typedef struct _ClutterPtrA11yData
|
||||
{
|
||||
int n_btn_pressed;
|
||||
@ -53,6 +91,26 @@ struct _ClutterInputDevice
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
int id;
|
||||
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterInputMode device_mode;
|
||||
|
||||
char *device_name;
|
||||
|
||||
ClutterSeat *seat;
|
||||
|
||||
ClutterBackend *backend;
|
||||
|
||||
/* the associated device */
|
||||
ClutterInputDevice *associated;
|
||||
|
||||
GList *slaves;
|
||||
|
||||
/* the actor underneath the pointer */
|
||||
ClutterActor *cursor_actor;
|
||||
GHashTable *inv_touch_sequence_actors;
|
||||
|
||||
/* the actor that has a grab in place for the device */
|
||||
ClutterActor *pointer_grab_actor;
|
||||
ClutterActor *keyboard_grab_actor;
|
||||
@ -61,17 +119,137 @@ struct _ClutterInputDevice
|
||||
|
||||
/* the current click count */
|
||||
int click_count;
|
||||
|
||||
/* the stage the device is on */
|
||||
ClutterStage *stage;
|
||||
|
||||
/* the current state */
|
||||
float current_x;
|
||||
float current_y;
|
||||
uint32_t current_time;
|
||||
int current_button_number;
|
||||
ClutterModifierType current_state;
|
||||
|
||||
/* the current touch points states */
|
||||
GHashTable *touch_sequences_info;
|
||||
|
||||
/* the previous state, used for click count generation */
|
||||
int previous_x;
|
||||
int previous_y;
|
||||
uint32_t previous_time;
|
||||
int previous_button_number;
|
||||
ClutterModifierType previous_state;
|
||||
|
||||
GArray *axes;
|
||||
|
||||
guint n_keys;
|
||||
GArray *keys;
|
||||
|
||||
GArray *scroll_info;
|
||||
|
||||
char *vendor_id;
|
||||
char *product_id;
|
||||
char *node_path;
|
||||
|
||||
GPtrArray *tools;
|
||||
|
||||
int n_rings;
|
||||
int n_strips;
|
||||
int n_mode_groups;
|
||||
|
||||
ClutterInputDeviceMapping mapping_mode;
|
||||
|
||||
guint has_cursor : 1;
|
||||
guint is_enabled : 1;
|
||||
|
||||
/* Accessiblity */
|
||||
ClutterVirtualInputDevice *accessibility_virtual_device;
|
||||
ClutterPtrA11yData *ptr_a11y_data;
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_associated_device (ClutterInputDevice *device,
|
||||
ClutterInputDevice *associated);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_add_slave (ClutterInputDevice *master,
|
||||
ClutterInputDevice *slave);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_remove_slave (ClutterInputDevice *master,
|
||||
ClutterInputDevice *slave);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_update_from_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * _clutter_input_device_get_stage (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||
ClutterStage *stage);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
ClutterStage *stage);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_state (ClutterInputDevice *device,
|
||||
ClutterModifierType state);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_time (ClutterInputDevice *device,
|
||||
guint32 time_);
|
||||
void _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
ClutterActor *actor,
|
||||
gboolean emit_crossing);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_update (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gboolean emit_crossing);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_add_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_remove_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
|
||||
guint n_keys);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
gdouble *axis_value);
|
||||
CLUTTER_EXPORT
|
||||
guint _clutter_input_device_add_axis (ClutterInputDevice *device,
|
||||
ClutterInputAxis axis,
|
||||
gdouble minimum,
|
||||
gdouble maximum,
|
||||
gdouble resolution);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_reset_axes (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_add_scroll_info (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
ClutterScrollDirection direction,
|
||||
gdouble increment);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_input_device_get_scroll_delta (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
ClutterScrollDirection *direction_p,
|
||||
gdouble *delta_p);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_reset_scroll_info (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_add_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceTool *
|
||||
clutter_input_device_lookup_tool (ClutterInputDevice *device,
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
|
||||
#endif /* CLUTTER_INPUT_DEVICE_PRIVATE_H */
|
||||
|
@ -33,7 +33,6 @@ struct _ClutterInputDeviceToolPrivate
|
||||
ClutterInputDeviceToolType type;
|
||||
guint64 serial;
|
||||
guint64 id;
|
||||
ClutterInputAxisFlags axes;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -42,7 +41,6 @@ enum
|
||||
PROP_TYPE,
|
||||
PROP_SERIAL,
|
||||
PROP_ID,
|
||||
PROP_AXES,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
@ -72,9 +70,6 @@ clutter_input_device_tool_set_property (GObject *object,
|
||||
case PROP_ID:
|
||||
priv->id = g_value_get_uint64 (value);
|
||||
break;
|
||||
case PROP_AXES:
|
||||
priv->axes = g_value_get_flags (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -102,9 +97,6 @@ clutter_input_device_tool_get_property (GObject *object,
|
||||
case PROP_ID:
|
||||
g_value_set_uint64 (value, priv->id);
|
||||
break;
|
||||
case PROP_AXES:
|
||||
g_value_set_flags (value, priv->axes);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -137,13 +129,6 @@ clutter_input_device_tool_class_init (ClutterInputDeviceToolClass *klass)
|
||||
P_("Tool ID"),
|
||||
0, G_MAXUINT64, 0,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
props[PROP_AXES] =
|
||||
g_param_spec_flags ("axes",
|
||||
P_("Axes"),
|
||||
P_("Axes"),
|
||||
CLUTTER_TYPE_INPUT_AXIS_FLAGS,
|
||||
CLUTTER_INPUT_AXIS_FLAG_NONE,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, props);
|
||||
}
|
||||
@ -219,15 +204,3 @@ clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool)
|
||||
|
||||
return priv->id;
|
||||
}
|
||||
|
||||
ClutterInputAxisFlags
|
||||
clutter_input_device_tool_get_axes (ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceToolPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0);
|
||||
|
||||
priv = clutter_input_device_tool_get_instance_private (tool);
|
||||
|
||||
return priv->axes;
|
||||
}
|
||||
|
@ -64,9 +64,6 @@ ClutterInputDeviceToolType clutter_input_device_tool_get_tool_type (ClutterInput
|
||||
CLUTTER_EXPORT
|
||||
guint64 clutter_input_device_tool_get_id (ClutterInputDeviceTool *tool);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputAxisFlags clutter_input_device_tool_get_axes (ClutterInputDeviceTool *tool);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_TOOL_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,10 +34,19 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef void (*ClutterEmitInputDeviceEvent) (ClutterEvent *event,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
struct _ClutterInputDeviceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* keycode_to_evdev) (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
void (* update_from_tool) (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
|
||||
gboolean (* is_mode_switch_button) (ClutterInputDevice *device,
|
||||
guint group,
|
||||
guint button);
|
||||
@ -47,9 +56,10 @@ struct _ClutterInputDeviceClass
|
||||
gboolean (* is_grouped) (ClutterInputDevice *device,
|
||||
ClutterInputDevice *other_device);
|
||||
|
||||
int (* get_pad_feature_group) (ClutterInputDevice *device,
|
||||
ClutterInputDevicePadFeature feature,
|
||||
int n_feature);
|
||||
/* Keyboard accessbility */
|
||||
void (* process_kbd_a11y_event) (ClutterEvent *event,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEmitInputDeviceEvent emit_event_func);
|
||||
};
|
||||
|
||||
#define CLUTTER_TYPE_INPUT_DEVICE (clutter_input_device_get_type ())
|
||||
@ -72,13 +82,65 @@ GType clutter_input_device_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceType clutter_input_device_get_device_type (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_device_id (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_coords (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *point);
|
||||
CLUTTER_EXPORT
|
||||
ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputMode clutter_input_device_get_device_mode (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_has_cursor (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_enabled (ClutterInputDevice *device,
|
||||
gboolean enabled);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_enabled (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_input_device_get_n_axes (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputAxis clutter_input_device_get_axis (ClutterInputDevice *device,
|
||||
guint index_);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_axis_value (ClutterInputDevice *device,
|
||||
gdouble *axes,
|
||||
ClutterInputAxis axis,
|
||||
gdouble *value);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_input_device_get_n_keys (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint keyval,
|
||||
ClutterModifierType modifiers);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint *keyval,
|
||||
ClutterModifierType *modifiers);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDevice * clutter_input_device_get_associated_device (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_input_device_get_slave_devices (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_update_from_event (ClutterInputDevice *device,
|
||||
ClutterEvent *event,
|
||||
gboolean update_stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_grab (ClutterInputDevice *device,
|
||||
@ -99,6 +161,11 @@ CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_sequence_get_grabbed_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_vendor_id (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
@ -110,9 +177,6 @@ CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_n_strips (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_n_mode_groups (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
int clutter_input_device_get_n_buttons (ClutterInputDevice *device);
|
||||
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_input_device_get_group_n_modes (ClutterInputDevice *device,
|
||||
@ -129,17 +193,18 @@ gint clutter_input_device_get_mode_switch_button_group (Clutt
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_device_node (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceMapping clutter_input_device_get_mapping_mode (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_mapping_mode (ClutterInputDevice *device,
|
||||
ClutterInputDeviceMapping mapping);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_is_grouped (ClutterInputDevice *device,
|
||||
ClutterInputDevice *other_device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterSeat * clutter_input_device_get_seat (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
int clutter_input_device_get_pad_feature_group (ClutterInputDevice *device,
|
||||
ClutterInputDevicePadFeature feature,
|
||||
int n_feature);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_H__ */
|
||||
|
@ -30,8 +30,6 @@ typedef struct _ClutterInputFocusPrivate ClutterInputFocusPrivate;
|
||||
struct _ClutterInputFocusPrivate
|
||||
{
|
||||
ClutterInputMethod *im;
|
||||
char *preedit;
|
||||
ClutterPreeditResetMode mode;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputFocus, clutter_input_focus, G_TYPE_OBJECT)
|
||||
@ -55,25 +53,9 @@ clutter_input_focus_real_focus_out (ClutterInputFocus *focus)
|
||||
priv->im = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_focus_finalize (GObject *object)
|
||||
{
|
||||
ClutterInputFocus *focus = CLUTTER_INPUT_FOCUS (object);
|
||||
ClutterInputFocusPrivate *priv =
|
||||
clutter_input_focus_get_instance_private (focus);
|
||||
|
||||
g_clear_pointer (&priv->preedit, g_free);
|
||||
|
||||
G_OBJECT_CLASS (clutter_input_focus_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_focus_class_init (ClutterInputFocusClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = clutter_input_focus_finalize;
|
||||
|
||||
klass->focus_in = clutter_input_focus_real_focus_in;
|
||||
klass->focus_out = clutter_input_focus_real_focus_out;
|
||||
}
|
||||
@ -103,16 +85,6 @@ clutter_input_focus_reset (ClutterInputFocus *focus)
|
||||
|
||||
priv = clutter_input_focus_get_instance_private (focus);
|
||||
|
||||
if (priv->preedit)
|
||||
{
|
||||
if (priv->mode == CLUTTER_PREEDIT_RESET_COMMIT)
|
||||
clutter_input_focus_commit (focus, priv->preedit);
|
||||
|
||||
clutter_input_focus_set_preedit_text (focus, NULL, 0);
|
||||
g_clear_pointer (&priv->preedit, g_free);
|
||||
}
|
||||
|
||||
priv->mode = CLUTTER_PREEDIT_RESET_CLEAR;
|
||||
clutter_input_method_reset (priv->im);
|
||||
}
|
||||
|
||||
@ -175,8 +147,8 @@ clutter_input_focus_set_content_purpose (ClutterInputFocus *focus,
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_input_focus_filter_event (ClutterInputFocus *focus,
|
||||
const ClutterEvent *event)
|
||||
clutter_input_focus_filter_key_event (ClutterInputFocus *focus,
|
||||
const ClutterKeyEvent *key)
|
||||
{
|
||||
ClutterInputFocusPrivate *priv;
|
||||
|
||||
@ -185,41 +157,7 @@ clutter_input_focus_filter_event (ClutterInputFocus *focus,
|
||||
|
||||
priv = clutter_input_focus_get_instance_private (focus);
|
||||
|
||||
if (event->type == CLUTTER_KEY_PRESS ||
|
||||
event->type == CLUTTER_KEY_RELEASE)
|
||||
{
|
||||
return clutter_input_method_filter_key_event (priv->im, &event->key);
|
||||
}
|
||||
else if (event->type == CLUTTER_IM_COMMIT)
|
||||
{
|
||||
clutter_input_focus_commit (focus, event->im.text);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_IM_DELETE)
|
||||
{
|
||||
clutter_input_focus_delete_surrounding (focus, event->im.offset,
|
||||
event->im.len);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_IM_PREEDIT)
|
||||
{
|
||||
g_clear_pointer (&priv->preedit, g_free);
|
||||
priv->preedit = g_strdup (event->im.text);
|
||||
priv->mode = event->im.mode;
|
||||
clutter_input_focus_set_preedit_text (focus, event->im.text,
|
||||
event->im.offset);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_TOUCH_BEGIN ||
|
||||
(event->type == CLUTTER_BUTTON_PRESS &&
|
||||
event->button.button == CLUTTER_BUTTON_PRIMARY))
|
||||
{
|
||||
clutter_input_focus_reset (focus);
|
||||
/* pointing events are not consumed by IMs */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return clutter_input_method_filter_key_event (priv->im, key);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -72,8 +72,8 @@ CLUTTER_EXPORT
|
||||
void clutter_input_focus_set_content_purpose (ClutterInputFocus *focus,
|
||||
ClutterInputContentPurpose purpose);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_focus_filter_event (ClutterInputFocus *focus,
|
||||
const ClutterEvent *event);
|
||||
gboolean clutter_input_focus_filter_key_event (ClutterInputFocus *focus,
|
||||
const ClutterKeyEvent *key);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
|
||||
gboolean can_show_preedit);
|
||||
|
@ -277,48 +277,17 @@ clutter_input_method_get_focus (ClutterInputMethod *im)
|
||||
return priv->focus;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_method_put_im_event (ClutterInputMethod *im,
|
||||
ClutterEventType event_type,
|
||||
const char *text,
|
||||
int32_t offset,
|
||||
uint32_t len,
|
||||
ClutterPreeditResetMode mode)
|
||||
{
|
||||
ClutterInputDevice *keyboard;
|
||||
ClutterSeat *seat;
|
||||
ClutterStageManager *stage_manager;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
keyboard = clutter_seat_get_keyboard (seat);
|
||||
stage_manager = clutter_stage_manager_get_default ();
|
||||
stage = clutter_stage_manager_get_default_stage (stage_manager);
|
||||
|
||||
event = clutter_event_new (event_type);
|
||||
event->im.text = g_strdup (text);
|
||||
event->im.offset = offset;
|
||||
event->im.len = len;
|
||||
event->im.mode = mode;
|
||||
clutter_event_set_device (event, keyboard);
|
||||
clutter_event_set_source_device (event, keyboard);
|
||||
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_INPUT_METHOD);
|
||||
|
||||
clutter_event_set_stage (event, stage);
|
||||
|
||||
clutter_event_put (event);
|
||||
clutter_event_free (event);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_method_commit (ClutterInputMethod *im,
|
||||
const gchar *text)
|
||||
{
|
||||
ClutterInputMethodPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
|
||||
|
||||
clutter_input_method_put_im_event (im, CLUTTER_IM_COMMIT, text, 0, 0,
|
||||
CLUTTER_PREEDIT_RESET_CLEAR);
|
||||
priv = clutter_input_method_get_instance_private (im);
|
||||
if (priv->focus)
|
||||
clutter_input_focus_commit (priv->focus, text);
|
||||
}
|
||||
|
||||
void
|
||||
@ -326,10 +295,13 @@ clutter_input_method_delete_surrounding (ClutterInputMethod *im,
|
||||
int offset,
|
||||
guint len)
|
||||
{
|
||||
ClutterInputMethodPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
|
||||
|
||||
clutter_input_method_put_im_event (im, CLUTTER_IM_DELETE, NULL, offset, len,
|
||||
CLUTTER_PREEDIT_RESET_CLEAR);
|
||||
priv = clutter_input_method_get_instance_private (im);
|
||||
if (priv->focus)
|
||||
clutter_input_focus_delete_surrounding (priv->focus, offset, len);
|
||||
}
|
||||
|
||||
void
|
||||
@ -353,15 +325,17 @@ clutter_input_method_request_surrounding (ClutterInputMethod *im)
|
||||
* Sets the preedit text on the current input focus.
|
||||
**/
|
||||
void
|
||||
clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
unsigned int cursor,
|
||||
ClutterPreeditResetMode mode)
|
||||
clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
guint cursor)
|
||||
{
|
||||
ClutterInputMethodPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
|
||||
|
||||
clutter_input_method_put_im_event (im, CLUTTER_IM_PREEDIT, preedit,
|
||||
cursor, 0, mode);
|
||||
priv = clutter_input_method_get_instance_private (im);
|
||||
if (priv->focus)
|
||||
clutter_input_focus_set_preedit_text (priv->focus, preedit, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -480,7 +454,6 @@ clutter_input_method_forward_key (ClutterInputMethod *im,
|
||||
ClutterInputMethodPrivate *priv;
|
||||
ClutterInputDevice *keyboard;
|
||||
ClutterSeat *seat;
|
||||
ClutterStageManager *stage_manager;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
@ -491,9 +464,10 @@ clutter_input_method_forward_key (ClutterInputMethod *im,
|
||||
return;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
stage_manager = clutter_stage_manager_get_default ();
|
||||
stage = clutter_stage_manager_get_default_stage (stage_manager);
|
||||
keyboard = clutter_seat_get_keyboard (seat);
|
||||
stage = _clutter_input_device_get_stage (keyboard);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
event = clutter_event_new (press ? CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
|
||||
event->key.time = time_;
|
||||
@ -501,7 +475,6 @@ clutter_input_method_forward_key (ClutterInputMethod *im,
|
||||
event->key.modifier_state = state;
|
||||
event->key.keyval = keyval;
|
||||
event->key.hardware_keycode = keycode;
|
||||
event->key.evdev_code = keycode - 8;
|
||||
event->key.unicode_value = clutter_keysym_to_unicode (keyval);
|
||||
|
||||
clutter_event_set_device (event, keyboard);
|
||||
|
@ -74,10 +74,9 @@ CLUTTER_EXPORT
|
||||
void clutter_input_method_request_surrounding (ClutterInputMethod *im);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
unsigned int cursor,
|
||||
ClutterPreeditResetMode mode);
|
||||
void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
|
||||
const gchar *preedit,
|
||||
guint cursor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_method_notify_key_event (ClutterInputMethod *im,
|
||||
|
@ -36,9 +36,8 @@ static gboolean
|
||||
is_secondary_click_enabled (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return (settings.controls & CLUTTER_A11Y_SECONDARY_CLICK_ENABLED);
|
||||
}
|
||||
@ -47,9 +46,8 @@ static gboolean
|
||||
is_dwell_click_enabled (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return (settings.controls & CLUTTER_A11Y_DWELL_ENABLED);
|
||||
}
|
||||
@ -58,9 +56,8 @@ static unsigned int
|
||||
get_secondary_click_delay (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.secondary_click_delay;
|
||||
}
|
||||
@ -69,9 +66,8 @@ static unsigned int
|
||||
get_dwell_delay (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_delay;
|
||||
}
|
||||
@ -80,9 +76,8 @@ static unsigned int
|
||||
get_dwell_threshold (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_threshold;
|
||||
}
|
||||
@ -91,9 +86,8 @@ static ClutterPointerA11yDwellMode
|
||||
get_dwell_mode (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_mode;
|
||||
}
|
||||
@ -102,9 +96,8 @@ static ClutterPointerA11yDwellClickType
|
||||
get_dwell_click_type (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
return settings.dwell_click_type;
|
||||
}
|
||||
@ -114,9 +107,8 @@ get_dwell_click_type_for_direction (ClutterInputDevice *device,
|
||||
ClutterPointerA11yDwellDirection direction)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
if (direction == settings.dwell_gesture_single)
|
||||
return CLUTTER_A11Y_DWELL_CLICK_TYPE_PRIMARY;
|
||||
@ -171,12 +163,11 @@ static gboolean
|
||||
trigger_secondary_click (gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = data;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->secondary_click_triggered = TRUE;
|
||||
device->ptr_a11y_data->secondary_click_timer = 0;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
|
||||
@ -189,12 +180,11 @@ static void
|
||||
start_secondary_click_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
unsigned int delay = get_secondary_click_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->secondary_click_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_secondary_click, device);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-started",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
|
||||
@ -204,14 +194,12 @@ start_secondary_click_timeout (ClutterInputDevice *device)
|
||||
static void
|
||||
stop_secondary_click_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (device->ptr_a11y_data->secondary_click_timer)
|
||||
{
|
||||
g_clear_handle_id (&device->ptr_a11y_data->secondary_click_timer,
|
||||
g_source_remove);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_SECONDARY_CLICK,
|
||||
@ -314,9 +302,8 @@ update_dwell_click_type (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterPointerA11ySettings settings;
|
||||
ClutterPointerA11yDwellClickType dwell_click_type;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_get_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
dwell_click_type = settings.dwell_click_type;
|
||||
switch (dwell_click_type)
|
||||
@ -341,9 +328,9 @@ update_dwell_click_type (ClutterInputDevice *device)
|
||||
if (dwell_click_type != settings.dwell_click_type)
|
||||
{
|
||||
settings.dwell_click_type = dwell_click_type;
|
||||
clutter_seat_set_pointer_a11y_settings (seat, &settings);
|
||||
clutter_seat_set_pointer_a11y_settings (device->seat, &settings);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-dwell-click-type-changed",
|
||||
dwell_click_type);
|
||||
}
|
||||
@ -437,7 +424,6 @@ trigger_dwell_gesture (gpointer data)
|
||||
ClutterInputDevice *device = data;
|
||||
ClutterPointerA11yDwellDirection direction;
|
||||
unsigned int delay = get_dwell_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
restore_dwell_position (device);
|
||||
direction = get_dwell_direction (device);
|
||||
@ -449,7 +435,7 @@ trigger_dwell_gesture (gpointer data)
|
||||
device->ptr_a11y_data->dwell_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_clear_dwell_gesture, device);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE,
|
||||
@ -462,13 +448,12 @@ static void
|
||||
start_dwell_gesture_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
unsigned int delay = get_dwell_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->dwell_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_dwell_gesture, device);
|
||||
device->ptr_a11y_data->dwell_gesture_started = TRUE;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-started",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_GESTURE,
|
||||
@ -479,11 +464,10 @@ static gboolean
|
||||
trigger_dwell_click (gpointer data)
|
||||
{
|
||||
ClutterInputDevice *device = data;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->dwell_timer = 0;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
|
||||
@ -509,12 +493,11 @@ static void
|
||||
start_dwell_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
unsigned int delay = get_dwell_delay (device);
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
device->ptr_a11y_data->dwell_timer =
|
||||
clutter_threads_add_timeout (delay, trigger_dwell_click, device);
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-started",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
|
||||
@ -524,14 +507,12 @@ start_dwell_timeout (ClutterInputDevice *device)
|
||||
static void
|
||||
stop_dwell_timeout (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (device->ptr_a11y_data->dwell_timer)
|
||||
{
|
||||
g_clear_handle_id (&device->ptr_a11y_data->dwell_timer, g_source_remove);
|
||||
device->ptr_a11y_data->dwell_gesture_started = FALSE;
|
||||
|
||||
g_signal_emit_by_name (seat,
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"ptr-a11y-timeout-stopped",
|
||||
device,
|
||||
CLUTTER_A11Y_TIMEOUT_TYPE_DWELL,
|
||||
@ -589,9 +570,8 @@ static gboolean
|
||||
is_device_core_pointer (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
core_pointer = clutter_seat_get_pointer (seat);
|
||||
core_pointer = clutter_seat_get_pointer (device->seat);
|
||||
if (core_pointer == NULL)
|
||||
return FALSE;
|
||||
|
||||
@ -601,13 +581,11 @@ is_device_core_pointer (ClutterInputDevice *device)
|
||||
void
|
||||
_clutter_input_pointer_a11y_add_device (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterSeat *seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (!is_device_core_pointer (device))
|
||||
return;
|
||||
|
||||
device->accessibility_virtual_device =
|
||||
clutter_seat_create_virtual_device (seat,
|
||||
clutter_seat_create_virtual_device (device->seat,
|
||||
CLUTTER_POINTER_DEVICE);
|
||||
|
||||
device->ptr_a11y_data = g_new0 (ClutterPtrA11yData, 1);
|
||||
|
@ -1176,7 +1176,7 @@ clutter_interval_compute_value (ClutterInterval *interval,
|
||||
* g_object_set_property()
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the computed value,
|
||||
* or %NULL if the computation was not successful
|
||||
* or %NULL if the computation was not successfull
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_KEYMAP_PRIVATE_H
|
||||
#define CLUTTER_KEYMAP_PRIVATE_H
|
||||
|
||||
#include "clutter/clutter-keymap.h"
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_keymap_set_lock_modifier_state (ClutterKeymap *keymap,
|
||||
gboolean caps_lock_state,
|
||||
gboolean num_lock_state);
|
||||
|
||||
#endif /* CLUTTER_KEYMAP_PRIVATE_H */
|
@ -21,29 +21,10 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-keymap-private.h"
|
||||
#include "clutter-keymap.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_CAPS_LOCK_STATE,
|
||||
PROP_NUM_LOCK_STATE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[N_PROPS];
|
||||
|
||||
typedef struct _ClutterKeymapPrivate
|
||||
{
|
||||
gboolean caps_lock_state;
|
||||
gboolean num_lock_state;
|
||||
} ClutterKeymapPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterKeymap, clutter_keymap,
|
||||
G_TYPE_OBJECT)
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterKeymap, clutter_keymap, G_TYPE_OBJECT)
|
||||
|
||||
enum
|
||||
{
|
||||
@ -53,76 +34,9 @@ enum
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0, };
|
||||
|
||||
static void
|
||||
clutter_keymap_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterKeymap *keymap = CLUTTER_KEYMAP (object);
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CAPS_LOCK_STATE:
|
||||
g_value_set_boolean (value, priv->caps_lock_state);
|
||||
break;
|
||||
case PROP_NUM_LOCK_STATE:
|
||||
g_value_set_boolean (value, priv->num_lock_state);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_keymap_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterKeymap *keymap = CLUTTER_KEYMAP (object);
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CAPS_LOCK_STATE:
|
||||
priv->caps_lock_state = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_NUM_LOCK_STATE:
|
||||
priv->num_lock_state = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_keymap_class_init (ClutterKeymapClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = clutter_keymap_get_property;
|
||||
object_class->set_property = clutter_keymap_set_property;
|
||||
|
||||
obj_props[PROP_CAPS_LOCK_STATE] =
|
||||
g_param_spec_boolean ("caps-lock-state",
|
||||
"Caps lock state",
|
||||
"Caps lock state",
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_props[PROP_NUM_LOCK_STATE] =
|
||||
g_param_spec_boolean ("num-lock-state",
|
||||
"Num lock state",
|
||||
"Num lock state",
|
||||
FALSE,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
|
||||
signals[STATE_CHANGED] =
|
||||
g_signal_new (I_("state-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
@ -140,17 +54,13 @@ clutter_keymap_init (ClutterKeymap *keymap)
|
||||
gboolean
|
||||
clutter_keymap_get_num_lock_state (ClutterKeymap *keymap)
|
||||
{
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
return priv->num_lock_state;
|
||||
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_num_lock_state (keymap);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_keymap_get_caps_lock_state (ClutterKeymap *keymap)
|
||||
{
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
return priv->caps_lock_state;
|
||||
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_caps_lock_state (keymap);
|
||||
}
|
||||
|
||||
PangoDirection
|
||||
@ -158,35 +68,3 @@ clutter_keymap_get_direction (ClutterKeymap *keymap)
|
||||
{
|
||||
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_direction (keymap);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_keymap_set_lock_modifier_state (ClutterKeymap *keymap,
|
||||
gboolean caps_lock_state,
|
||||
gboolean num_lock_state)
|
||||
{
|
||||
ClutterKeymapPrivate *priv = clutter_keymap_get_instance_private (keymap);
|
||||
|
||||
if (priv->caps_lock_state == caps_lock_state &&
|
||||
priv->num_lock_state == num_lock_state)
|
||||
return;
|
||||
|
||||
if (priv->caps_lock_state != caps_lock_state)
|
||||
{
|
||||
priv->caps_lock_state = caps_lock_state;
|
||||
g_object_notify_by_pspec (G_OBJECT (keymap),
|
||||
obj_props[PROP_CAPS_LOCK_STATE]);
|
||||
}
|
||||
|
||||
if (priv->num_lock_state != num_lock_state)
|
||||
{
|
||||
priv->num_lock_state = num_lock_state;
|
||||
g_object_notify_by_pspec (G_OBJECT (keymap),
|
||||
obj_props[PROP_NUM_LOCK_STATE]);
|
||||
}
|
||||
|
||||
g_debug ("Locks state changed - Num: %s, Caps: %s",
|
||||
priv->num_lock_state ? "set" : "unset",
|
||||
priv->caps_lock_state ? "set" : "unset");
|
||||
|
||||
g_signal_emit (keymap, signals[STATE_CHANGED], 0);
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ struct _ClutterKeymapClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* get_num_lock_state) (ClutterKeymap *keymap);
|
||||
gboolean (* get_caps_lock_state) (ClutterKeymap *keymap);
|
||||
PangoDirection (* get_direction) (ClutterKeymap *keymap);
|
||||
};
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# Author : Simos Xenitellis <simos at gnome dot org>.
|
||||
# Author : Bastien Nocera <hadess@hadess.net>
|
||||
# Authos : Bastien Nocera <hadess@hadess.net>
|
||||
# Version : 1.2
|
||||
#
|
||||
# Notes : It downloads keysymdef.h from the Internet, if not found locally,
|
||||
|
@ -41,7 +41,7 @@
|
||||
* The implementation of a layout manager does not differ from the
|
||||
* implementation of the size requisition and allocation bits of
|
||||
* #ClutterActor, so you should read the relative documentation
|
||||
* for subclassing #ClutterActor.
|
||||
* forr subclassing #ClutterActor.
|
||||
*
|
||||
* The layout manager implementation can hold a back pointer to the
|
||||
* #ClutterContainer by implementing the #ClutterLayoutManagerClass.set_container()
|
||||
|
@ -84,7 +84,7 @@ struct _ClutterLayoutManager
|
||||
* in newly written code.
|
||||
* @end_animation: virtual function; override to end an animation started
|
||||
* by clutter_layout_manager_begin_animation(). This virtual function is
|
||||
* deprecated, and it should not be overridden in newly written code.
|
||||
* deprecated, and it should not be overriden in newly written code.
|
||||
* @get_animation_progress: virtual function; override to control the
|
||||
* progress of the animation of a #ClutterLayoutManager. This virtual
|
||||
* function is deprecated, and it should not be overridden in newly written
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -53,8 +53,6 @@ typedef enum
|
||||
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
|
||||
CLUTTER_DEBUG_CLIPPING = 1 << 15,
|
||||
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16,
|
||||
CLUTTER_DEBUG_FRAME_TIMINGS = 1 << 17,
|
||||
CLUTTER_DEBUG_DETAILED_TRACE = 1 << 18,
|
||||
} ClutterDebugFlag;
|
||||
|
||||
typedef enum
|
||||
@ -64,17 +62,15 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
|
||||
CLUTTER_DEBUG_REDRAWS = 1 << 2,
|
||||
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
|
||||
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
|
||||
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
|
||||
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
|
||||
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
|
||||
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
|
||||
CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME = 1 << 9,
|
||||
CLUTTER_DEBUG_PAINT_MAX_RENDER_TIME = 1 << 10,
|
||||
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
|
||||
CLUTTER_DEBUG_REDRAWS = 1 << 2,
|
||||
CLUTTER_DEBUG_PAINT_VOLUMES = 1 << 3,
|
||||
CLUTTER_DEBUG_DISABLE_CULLING = 1 << 4,
|
||||
CLUTTER_DEBUG_DISABLE_OFFSCREEN_REDIRECT = 1 << 5,
|
||||
CLUTTER_DEBUG_CONTINUOUS_REDRAW = 1 << 6,
|
||||
CLUTTER_DEBUG_PAINT_DEFORM_TILES = 1 << 7,
|
||||
CLUTTER_DEBUG_PAINT_DAMAGE_REGION = 1 << 8,
|
||||
} ClutterDrawDebugFlag;
|
||||
|
||||
/**
|
||||
@ -92,7 +88,7 @@ typedef enum
|
||||
* @CLUTTER_INIT_ERROR_BACKEND: Backend initialisation failed
|
||||
* @CLUTTER_INIT_ERROR_INTERNAL: Internal error
|
||||
*
|
||||
* Error conditions returned by clutter_init().
|
||||
* Error conditions returned by clutter_init() and clutter_init_with_args().
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
@ -127,12 +123,27 @@ void clutter_base_init (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInitError clutter_init (int *argc,
|
||||
char ***argv) G_GNUC_WARN_UNUSED_RESULT;
|
||||
CLUTTER_EXPORT
|
||||
ClutterInitError clutter_init_with_args (int *argc,
|
||||
char ***argv,
|
||||
const char *parameter_string,
|
||||
GOptionEntry *entries,
|
||||
const char *translation_domain,
|
||||
GError **error) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GOptionGroup * clutter_get_option_group (void);
|
||||
CLUTTER_EXPORT
|
||||
GOptionGroup * clutter_get_option_group_without_init (void);
|
||||
|
||||
/* Mainloop */
|
||||
CLUTTER_EXPORT
|
||||
void clutter_main (void);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_main_quit (void);
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_main_level (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_do_event (ClutterEvent *event);
|
||||
|
||||
@ -183,6 +194,9 @@ ClutterTextDirection clutter_get_default_text_direction (void);
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_get_default_frame_rate (void);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_check_windowing_backend (const char *backend_type);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_add_debug_flags (ClutterDebugFlag debug_flags,
|
||||
ClutterDrawDebugFlag draw_flags,
|
||||
@ -193,9 +207,6 @@ void clutter_remove_debug_flags (ClutterDebugFla
|
||||
ClutterDrawDebugFlag draw_flags,
|
||||
ClutterPickDebugFlag pick_flags);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_debug_set_max_render_time_constant (int max_render_time_constant_us);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _CLUTTER_MAIN_H__ */
|
||||
|
@ -26,8 +26,6 @@
|
||||
#define __CLUTTER_H_INSIDE__
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-backend-private.h"
|
||||
#include "clutter-damage-history.h"
|
||||
#include "clutter-event-private.h"
|
||||
#include "clutter-input-device-private.h"
|
||||
#include "clutter-input-pointer-a11y-private.h"
|
||||
@ -35,8 +33,8 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-stage-view.h"
|
||||
#include "clutter-stage-view-private.h"
|
||||
#include "clutter.h"
|
||||
#include "cogl/clutter-stage-cogl.h"
|
||||
#include "clutter/x11/clutter-backend-x11.h"
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_stage_peek_stage_views (ClutterStage *stage);
|
||||
@ -52,11 +50,27 @@ CLUTTER_EXPORT
|
||||
int64_t clutter_stage_get_frame_counter (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_capture_view_into (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
cairo_rectangle_int_t *rect,
|
||||
uint8_t *data,
|
||||
int stride);
|
||||
void clutter_stage_capture_into (ClutterStage *stage,
|
||||
gboolean paint,
|
||||
cairo_rectangle_int_t *rect,
|
||||
uint8_t *data);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_paint_to_framebuffer (ClutterStage *stage,
|
||||
CoglFramebuffer *framebuffer,
|
||||
const cairo_rectangle_int_t *rect,
|
||||
float scale,
|
||||
ClutterPaintFlag paint_flags);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
|
||||
const cairo_rectangle_int_t *rect,
|
||||
float scale,
|
||||
uint8_t *data,
|
||||
int stride,
|
||||
CoglPixelFormat format,
|
||||
ClutterPaintFlag paint_flags,
|
||||
GError **error);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_clear_stage_views (ClutterStage *stage);
|
||||
@ -71,36 +85,6 @@ gboolean clutter_actor_has_damage (ClutterActor *actor);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_transitions (ClutterActor *actor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_actor_pick_frame_clock (ClutterActor *self,
|
||||
ClutterActor **out_actor);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_seat_handle_event_post (ClutterSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_update_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t point,
|
||||
uint32_t time,
|
||||
ClutterActor *new_actor,
|
||||
gboolean emit_crossing);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_get_device_coords (ClutterStage *stage,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_repick_device (ClutterStage *stage,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_get_debug_flags (ClutterDebugFlag *debug_flags,
|
||||
ClutterDrawDebugFlag *draw_flags,
|
||||
ClutterPickDebugFlag *pick_flags);
|
||||
|
||||
#undef __CLUTTER_H_INSIDE__
|
||||
|
||||
#endif /* __CLUTTER_MUTTER_H__ */
|
||||
|
@ -63,7 +63,7 @@
|
||||
*
|
||||
* ## Paint nodes
|
||||
*
|
||||
* #ClutterOffscreenEffect generates the following paint node tree:
|
||||
* #ClutterOffscreenEffect is generates the following paint node tree:
|
||||
*
|
||||
* |[<!-- language="plain" -->
|
||||
* Effect
|
||||
@ -106,7 +106,7 @@
|
||||
|
||||
struct _ClutterOffscreenEffectPrivate
|
||||
{
|
||||
CoglOffscreen *offscreen;
|
||||
CoglHandle offscreen;
|
||||
CoglPipeline *pipeline;
|
||||
CoglHandle texture;
|
||||
|
||||
@ -123,7 +123,7 @@ struct _ClutterOffscreenEffectPrivate
|
||||
int target_width;
|
||||
int target_height;
|
||||
|
||||
gulong purge_handler_id;
|
||||
gint old_opacity_override;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterOffscreenEffect,
|
||||
@ -142,7 +142,7 @@ clutter_offscreen_effect_set_actor (ClutterActorMeta *meta,
|
||||
meta_class->set_actor (meta, actor);
|
||||
|
||||
/* clear out the previous state */
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
/* we keep a back pointer here, to avoid going through the ActorMeta */
|
||||
priv->actor = clutter_actor_meta_get_actor (meta);
|
||||
@ -201,12 +201,6 @@ clutter_offscreen_effect_real_create_pipeline (ClutterOffscreenEffect *effect,
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
video_memory_purged (ClutterOffscreenEffect *self)
|
||||
{
|
||||
g_clear_object (&self->priv->offscreen);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_fbo (ClutterEffect *effect,
|
||||
int target_width,
|
||||
@ -214,31 +208,11 @@ update_fbo (ClutterEffect *effect,
|
||||
float resource_scale)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectClass *offscreen_class =
|
||||
CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (self);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
ClutterActor *stage_actor;
|
||||
CoglOffscreen *offscreen;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
stage_actor = clutter_actor_get_stage (priv->actor);
|
||||
if (stage_actor != priv->stage)
|
||||
{
|
||||
g_clear_signal_handler (&priv->purge_handler_id, priv->stage);
|
||||
|
||||
priv->stage = stage_actor;
|
||||
|
||||
if (priv->stage)
|
||||
{
|
||||
priv->purge_handler_id =
|
||||
g_signal_connect_object (priv->stage,
|
||||
"gl-video-memory-purged",
|
||||
G_CALLBACK (video_memory_purged),
|
||||
self,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
}
|
||||
ClutterOffscreenEffectClass *offscreen_class =
|
||||
CLUTTER_OFFSCREEN_EFFECT_GET_CLASS (effect);
|
||||
|
||||
priv->stage = clutter_actor_get_stage (priv->actor);
|
||||
if (priv->stage == NULL)
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "The actor '%s' is not part of a stage",
|
||||
@ -257,7 +231,7 @@ update_fbo (ClutterEffect *effect,
|
||||
}
|
||||
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
priv->texture =
|
||||
clutter_offscreen_effect_create_texture (self, target_width, target_height);
|
||||
@ -267,13 +241,11 @@ update_fbo (ClutterEffect *effect,
|
||||
priv->target_width = target_width;
|
||||
priv->target_height = target_height;
|
||||
|
||||
offscreen = cogl_offscreen_new_with_texture (priv->texture);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
|
||||
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
|
||||
if (priv->offscreen == NULL)
|
||||
{
|
||||
g_warning ("Failed to create offscreen effect framebuffer: %s",
|
||||
error->message);
|
||||
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
|
||||
|
||||
g_object_unref (offscreen);
|
||||
cogl_clear_object (&priv->pipeline);
|
||||
|
||||
priv->target_width = 0;
|
||||
@ -282,8 +254,6 @@ update_fbo (ClutterEffect *effect,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->offscreen = offscreen;
|
||||
|
||||
cogl_clear_object (&priv->pipeline);
|
||||
priv->pipeline = offscreen_class->create_pipeline (self, priv->texture);
|
||||
|
||||
@ -297,10 +267,9 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
CoglFramebuffer *offscreen;
|
||||
ClutterActorBox raw_box, box;
|
||||
ClutterActor *stage;
|
||||
graphene_matrix_t projection, modelview, transform;
|
||||
CoglMatrix projection, modelview;
|
||||
const ClutterPaintVolume *volume;
|
||||
gfloat stage_width, stage_height;
|
||||
gfloat target_width = -1, target_height = -1;
|
||||
@ -308,10 +277,10 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
float ceiled_resource_scale;
|
||||
|
||||
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
|
||||
goto disable_effect;
|
||||
goto fail;
|
||||
|
||||
if (priv->actor == NULL)
|
||||
goto disable_effect;
|
||||
goto fail;
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (priv->actor);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
@ -336,24 +305,18 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
_clutter_paint_volume_copy_static (volume, &mutable_volume);
|
||||
_clutter_paint_volume_get_bounding_box (&mutable_volume, &raw_box);
|
||||
clutter_paint_volume_free (&mutable_volume);
|
||||
|
||||
box = raw_box;
|
||||
_clutter_actor_box_enlarge_for_effects (&box);
|
||||
|
||||
priv->fbo_offset_x = box.x1;
|
||||
priv->fbo_offset_y = box.y1;
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_actor_get_allocation_box (priv->actor, &raw_box);
|
||||
|
||||
box = raw_box;
|
||||
_clutter_actor_box_enlarge_for_effects (&box);
|
||||
|
||||
priv->fbo_offset_x = box.x1 - raw_box.x1;
|
||||
priv->fbo_offset_y = box.y1 - raw_box.y1;
|
||||
}
|
||||
|
||||
box = raw_box;
|
||||
_clutter_actor_box_enlarge_for_effects (&box);
|
||||
|
||||
priv->fbo_offset_x = box.x1 - raw_box.x1;
|
||||
priv->fbo_offset_y = box.y1 - raw_box.y1;
|
||||
|
||||
clutter_actor_box_scale (&box, ceiled_resource_scale);
|
||||
clutter_actor_box_get_size (&box, &target_width, &target_height);
|
||||
|
||||
@ -362,9 +325,7 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
|
||||
/* First assert that the framebuffer is the right size... */
|
||||
if (!update_fbo (effect, target_width, target_height, resource_scale))
|
||||
goto disable_effect;
|
||||
|
||||
offscreen = COGL_FRAMEBUFFER (priv->offscreen);
|
||||
goto fail;
|
||||
|
||||
/* We don't want the FBO contents to be transformed. That could waste memory
|
||||
* (e.g. during zoom), or result in something that's not rectangular (clipped
|
||||
@ -374,36 +335,27 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
* contents on screen...
|
||||
*/
|
||||
clutter_actor_get_transform (priv->stage, &modelview);
|
||||
graphene_matrix_init_translate (&transform,
|
||||
&GRAPHENE_POINT3D_INIT (-priv->fbo_offset_x,
|
||||
-priv->fbo_offset_y,
|
||||
0.0));
|
||||
graphene_matrix_scale (&transform,
|
||||
stage_width / target_width,
|
||||
stage_height / target_height,
|
||||
1.0);
|
||||
graphene_matrix_multiply (&transform, &modelview, &modelview);
|
||||
cogl_framebuffer_set_modelview_matrix (offscreen, &modelview);
|
||||
cogl_framebuffer_set_modelview_matrix (priv->offscreen, &modelview);
|
||||
|
||||
/* Set up the viewport so that it has the minimal size required to render any
|
||||
* pixel in the FBO without clipping.
|
||||
/* Set up the viewport so that it has the same size as the stage (avoid
|
||||
* distortion), but translated to account for the FBO offset...
|
||||
*/
|
||||
cogl_framebuffer_set_viewport (offscreen,
|
||||
0,
|
||||
0,
|
||||
target_width,
|
||||
target_height);
|
||||
cogl_framebuffer_set_viewport (priv->offscreen,
|
||||
-priv->fbo_offset_x,
|
||||
-priv->fbo_offset_y,
|
||||
stage_width,
|
||||
stage_height);
|
||||
|
||||
/* Copy the stage's projection matrix across to the offscreen */
|
||||
/* Copy the stage's projection matrix across to the framebuffer */
|
||||
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage),
|
||||
&projection);
|
||||
|
||||
cogl_framebuffer_set_projection_matrix (offscreen, &projection);
|
||||
cogl_framebuffer_set_projection_matrix (priv->offscreen, &projection);
|
||||
|
||||
return TRUE;
|
||||
|
||||
disable_effect:
|
||||
g_clear_object (&priv->offscreen);
|
||||
fail:
|
||||
cogl_clear_object (&priv->offscreen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -450,17 +402,25 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||
graphene_matrix_t transform;
|
||||
float unscale;
|
||||
CoglMatrix transform;
|
||||
float resource_scale;
|
||||
|
||||
unscale = 1.0 / clutter_actor_get_resource_scale (priv->actor);
|
||||
graphene_matrix_init_scale (&transform, unscale, unscale, 1.0);
|
||||
graphene_matrix_translate (&transform,
|
||||
&GRAPHENE_POINT3D_INIT (priv->fbo_offset_x,
|
||||
priv->fbo_offset_y,
|
||||
0.0));
|
||||
cogl_matrix_init_identity (&transform);
|
||||
|
||||
if (!graphene_matrix_is_identity (&transform))
|
||||
resource_scale = clutter_actor_get_resource_scale (priv->actor);
|
||||
|
||||
if (resource_scale != 1.0f)
|
||||
{
|
||||
float paint_scale = 1.0f / resource_scale;
|
||||
cogl_matrix_scale (&transform, paint_scale, paint_scale, 1);
|
||||
}
|
||||
|
||||
cogl_matrix_translate (&transform,
|
||||
priv->fbo_offset_x,
|
||||
priv->fbo_offset_y,
|
||||
0.0f);
|
||||
|
||||
if (!cogl_matrix_is_identity (&transform))
|
||||
{
|
||||
ClutterPaintNode *transform_node;
|
||||
|
||||
@ -494,19 +454,6 @@ clutter_offscreen_effect_post_paint (ClutterEffect *effect,
|
||||
clutter_offscreen_effect_paint_texture (self, node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
add_actor_node (ClutterOffscreenEffect *offscreen_effect,
|
||||
ClutterPaintNode *node,
|
||||
int paint_opacity)
|
||||
{
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
ClutterPaintNode *actor_node;
|
||||
|
||||
actor_node = clutter_actor_node_new (priv->actor, paint_opacity);
|
||||
clutter_paint_node_add_child (node, actor_node);
|
||||
clutter_paint_node_unref (actor_node);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_paint_node (ClutterEffect *effect,
|
||||
ClutterPaintNode *node,
|
||||
@ -516,16 +463,19 @@ clutter_offscreen_effect_paint_node (ClutterEffect *effect,
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
ClutterPaintNode *layer_node;
|
||||
CoglFramebuffer *fb;
|
||||
ClutterPaintNode *actor_node;
|
||||
|
||||
fb = COGL_FRAMEBUFFER (priv->offscreen);
|
||||
layer_node = clutter_layer_node_new_to_framebuffer (fb, priv->pipeline);
|
||||
layer_node = clutter_layer_node_new_with_framebuffer (priv->offscreen,
|
||||
priv->pipeline,
|
||||
255);
|
||||
clutter_paint_node_set_static_name (layer_node,
|
||||
"ClutterOffscreenEffect (actor offscreen)");
|
||||
clutter_paint_node_add_child (node, layer_node);
|
||||
clutter_paint_node_unref (layer_node);
|
||||
|
||||
add_actor_node (offscreen_effect, layer_node, 255);
|
||||
actor_node = clutter_actor_node_new (priv->actor, 255);
|
||||
clutter_paint_node_add_child (layer_node, actor_node);
|
||||
clutter_paint_node_unref (actor_node);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -541,8 +491,8 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
|
||||
if (flags & CLUTTER_EFFECT_PAINT_BYPASS_EFFECT)
|
||||
{
|
||||
add_actor_node (self, node, -1);
|
||||
g_clear_object (&priv->offscreen);
|
||||
parent_class->paint_node (effect, node, paint_context, flags);
|
||||
cogl_clear_object (&priv->offscreen);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -564,7 +514,7 @@ clutter_offscreen_effect_set_enabled (ClutterActorMeta *meta,
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (meta);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
parent_class->set_enabled (meta, is_enabled);
|
||||
}
|
||||
@ -575,7 +525,7 @@ clutter_offscreen_effect_finalize (GObject *gobject)
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (gobject);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
|
||||
g_clear_object (&priv->offscreen);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
|
||||
|
@ -20,17 +20,12 @@
|
||||
|
||||
#include "clutter-paint-context.h"
|
||||
|
||||
ClutterPaintContext *
|
||||
clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip,
|
||||
GArray *clip_frusta,
|
||||
ClutterPaintFlag paint_flags);
|
||||
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip,
|
||||
ClutterPaintFlag paint_flags);
|
||||
|
||||
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);
|
||||
|
||||
CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context);
|
||||
|
||||
const GArray *
|
||||
clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context);
|
||||
|
||||
#endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */
|
||||
|
@ -30,7 +30,6 @@ struct _ClutterPaintContext
|
||||
ClutterStageView *view;
|
||||
|
||||
cairo_region_t *redraw_clip;
|
||||
GArray *clip_frusta;
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
|
||||
@ -40,7 +39,6 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
|
||||
ClutterPaintContext *
|
||||
clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip,
|
||||
GArray *clip_frusta,
|
||||
ClutterPaintFlag paint_flags)
|
||||
{
|
||||
ClutterPaintContext *paint_context;
|
||||
@ -50,7 +48,6 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
g_ref_count_init (&paint_context->ref_count);
|
||||
paint_context->view = view;
|
||||
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
|
||||
paint_context->clip_frusta = g_array_ref (clip_frusta);
|
||||
paint_context->paint_flags = paint_flags;
|
||||
|
||||
framebuffer = clutter_stage_view_get_framebuffer (view);
|
||||
@ -89,10 +86,10 @@ clutter_paint_context_ref (ClutterPaintContext *paint_context)
|
||||
static void
|
||||
clutter_paint_context_dispose (ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_list_free_full (paint_context->framebuffers, g_object_unref);
|
||||
g_list_free_full (paint_context->framebuffers,
|
||||
cogl_object_unref);
|
||||
paint_context->framebuffers = NULL;
|
||||
g_clear_pointer (&paint_context->redraw_clip, cairo_region_destroy);
|
||||
g_clear_pointer (&paint_context->clip_frusta, g_array_unref);
|
||||
}
|
||||
|
||||
void
|
||||
@ -117,7 +114,7 @@ clutter_paint_context_push_framebuffer (ClutterPaintContext *paint_context,
|
||||
CoglFramebuffer *framebuffer)
|
||||
{
|
||||
paint_context->framebuffers = g_list_prepend (paint_context->framebuffers,
|
||||
g_object_ref (framebuffer));
|
||||
cogl_object_ref (framebuffer));
|
||||
}
|
||||
|
||||
void
|
||||
@ -125,7 +122,7 @@ clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context)
|
||||
{
|
||||
g_return_if_fail (paint_context->framebuffers);
|
||||
|
||||
g_object_unref (paint_context->framebuffers->data);
|
||||
cogl_object_unref (paint_context->framebuffers->data);
|
||||
paint_context->framebuffers =
|
||||
g_list_delete_link (paint_context->framebuffers,
|
||||
paint_context->framebuffers);
|
||||
@ -137,12 +134,6 @@ clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context)
|
||||
return paint_context->redraw_clip;
|
||||
}
|
||||
|
||||
const GArray *
|
||||
clutter_paint_context_get_clip_frusta (ClutterPaintContext *paint_context)
|
||||
{
|
||||
return paint_context->clip_frusta;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_context_get_framebuffer:
|
||||
* @paint_context: The #ClutterPaintContext
|
||||
|
@ -33,8 +33,6 @@ typedef enum _ClutterPaintFlag
|
||||
{
|
||||
CLUTTER_PAINT_FLAG_NONE = 0,
|
||||
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
|
||||
CLUTTER_PAINT_FLAG_FORCE_CURSORS = 1 << 1,
|
||||
CLUTTER_PAINT_FLAG_CLEAR = 1 << 2,
|
||||
} ClutterPaintFlag;
|
||||
|
||||
#define CLUTTER_TYPE_PAINT_CONTEXT (clutter_paint_context_get_type ())
|
||||
|
@ -82,7 +82,6 @@ typedef enum
|
||||
{
|
||||
PAINT_OP_INVALID = 0,
|
||||
PAINT_OP_TEX_RECT,
|
||||
PAINT_OP_TEX_RECTS,
|
||||
PAINT_OP_MULTITEX_RECT,
|
||||
PAINT_OP_PRIMITIVE
|
||||
} PaintOpCode;
|
||||
@ -91,7 +90,7 @@ struct _ClutterPaintOperation
|
||||
{
|
||||
PaintOpCode opcode;
|
||||
|
||||
GArray *coords;
|
||||
GArray *multitex_coords;
|
||||
|
||||
union {
|
||||
float texrect[8];
|
||||
@ -112,7 +111,7 @@ void _clutter_paint_operation_paint_primitive (const C
|
||||
void _clutter_paint_node_init_types (void);
|
||||
gpointer _clutter_paint_node_create (GType gtype);
|
||||
|
||||
ClutterPaintNode * _clutter_transform_node_new (const graphene_matrix_t *matrix);
|
||||
ClutterPaintNode * _clutter_transform_node_new (const CoglMatrix *matrix);
|
||||
ClutterPaintNode * _clutter_dummy_node_new (ClutterActor *actor,
|
||||
CoglFramebuffer *framebuffer);
|
||||
|
||||
@ -160,7 +159,7 @@ CLUTTER_EXPORT
|
||||
GType clutter_effect_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_effect_node_new (ClutterEffect *effect);
|
||||
ClutterPaintNode * clutter_effect_node_new (ClutterEffect *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -60,6 +60,8 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <cogl/cogl.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
@ -234,9 +236,9 @@ clutter_paint_node_init (ClutterPaintNode *self)
|
||||
GType
|
||||
clutter_paint_node_get_type (void)
|
||||
{
|
||||
static size_t paint_node_type_id = 0;
|
||||
static volatile gsize paint_node_type_id__volatile = 0;
|
||||
|
||||
if (g_once_init_enter (&paint_node_type_id))
|
||||
if (g_once_init_enter (&paint_node_type_id__volatile))
|
||||
{
|
||||
static const GTypeFundamentalInfo finfo = {
|
||||
(G_TYPE_FLAG_CLASSED |
|
||||
@ -272,16 +274,16 @@ clutter_paint_node_get_type (void)
|
||||
&value_table,
|
||||
};
|
||||
|
||||
GType id =
|
||||
GType paint_node_type_id =
|
||||
g_type_register_fundamental (g_type_fundamental_next (),
|
||||
I_("ClutterPaintNode"),
|
||||
&node_info, &finfo,
|
||||
G_TYPE_FLAG_ABSTRACT);
|
||||
|
||||
g_once_init_leave (&paint_node_type_id, id);
|
||||
g_once_init_leave (&paint_node_type_id__volatile, paint_node_type_id);
|
||||
}
|
||||
|
||||
return paint_node_type_id;
|
||||
return paint_node_type_id__volatile;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -775,9 +777,9 @@ clutter_paint_operation_clear (ClutterPaintOperation *op)
|
||||
case PAINT_OP_TEX_RECT:
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
g_clear_pointer (&op->coords, g_array_unref);
|
||||
if (op->multitex_coords != NULL)
|
||||
g_array_unref (op->multitex_coords);
|
||||
break;
|
||||
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
@ -808,36 +810,6 @@ clutter_paint_op_init_tex_rect (ClutterPaintOperation *op,
|
||||
op->op.texrect[7] = y_2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_paint_op_init_tex_rects (ClutterPaintOperation *op,
|
||||
const float *coords,
|
||||
unsigned int n_rects,
|
||||
gboolean use_default_tex_coords)
|
||||
{
|
||||
const unsigned int n_floats = n_rects * 8;
|
||||
|
||||
clutter_paint_operation_clear (op);
|
||||
|
||||
op->opcode = PAINT_OP_TEX_RECTS;
|
||||
op->coords = g_array_sized_new (FALSE, FALSE, sizeof (float), n_floats);
|
||||
|
||||
if (use_default_tex_coords)
|
||||
{
|
||||
const float default_tex_coords[4] = { 0.0, 0.0, 1.0, 1.0 };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
g_array_append_vals (op->coords, &coords[i * 4], 4);
|
||||
g_array_append_vals (op->coords, default_tex_coords, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_array_append_vals (op->coords, coords, n_floats);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
|
||||
const ClutterActorBox *rect,
|
||||
@ -847,11 +819,11 @@ clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
|
||||
clutter_paint_operation_clear (op);
|
||||
|
||||
op->opcode = PAINT_OP_MULTITEX_RECT;
|
||||
op->coords = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (float),
|
||||
tex_coords_len);
|
||||
op->multitex_coords = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (float),
|
||||
tex_coords_len);
|
||||
|
||||
g_array_append_vals (op->coords, tex_coords, tex_coords_len);
|
||||
g_array_append_vals (op->multitex_coords, tex_coords, tex_coords_len);
|
||||
|
||||
op->op.texrect[0] = rect->x1;
|
||||
op->op.texrect[1] = rect->y1;
|
||||
@ -963,74 +935,6 @@ clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node,
|
||||
g_array_append_val (node->operations, operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_add_rectangles:
|
||||
* @node: a #ClutterPaintNode
|
||||
* @coords: (in) (array length=n_rects) (transfer none): array of
|
||||
* coordinates containing groups of 4 float values: [x_1, y_1, x_2, y_2] that
|
||||
* are interpreted as two position coordinates; one for the top left of the
|
||||
* rectangle (x1, y1), and one for the bottom right of the rectangle
|
||||
* (x2, y2).
|
||||
* @n_rects: number of rectangles defined in @coords.
|
||||
*
|
||||
* Adds a series of rectangles to @node.
|
||||
*
|
||||
* As a general rule for better performance its recommended to use this API
|
||||
* instead of calling clutter_paint_node_add_rectangle() separately for
|
||||
* multiple rectangles if all of the rectangles will be drawn together.
|
||||
*
|
||||
* See cogl_framebuffer_draw_rectangles().
|
||||
*/
|
||||
void
|
||||
clutter_paint_node_add_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects)
|
||||
{
|
||||
ClutterPaintOperation operation = PAINT_OP_INIT;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
|
||||
g_return_if_fail (coords != NULL);
|
||||
|
||||
clutter_paint_node_maybe_init_operations (node);
|
||||
|
||||
clutter_paint_op_init_tex_rects (&operation, coords, n_rects, TRUE);
|
||||
g_array_append_val (node->operations, operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_add_texture_rectangles:
|
||||
* @node: a #ClutterPaintNode
|
||||
* @coords: (in) (array length=n_rects) (transfer none): array containing
|
||||
* groups of 8 float values: [x_1, y_1, x_2, y_2, s_1, t_1, s_2, t_2]
|
||||
* that have the same meaning as the arguments for
|
||||
* cogl_framebuffer_draw_textured_rectangle().
|
||||
* @n_rects: number of rectangles defined in @coords.
|
||||
*
|
||||
* Adds a series of rectangles to @node.
|
||||
*
|
||||
* The given texture coordinates should always be normalized such that
|
||||
* (0, 0) corresponds to the top left and (1, 1) corresponds to the
|
||||
* bottom right. To map an entire texture across the rectangle pass
|
||||
* in s_1=0, t_1=0, s_2=1, t_2=1.
|
||||
*
|
||||
* See cogl_framebuffer_draw_textured_rectangles().
|
||||
*/
|
||||
void
|
||||
clutter_paint_node_add_texture_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects)
|
||||
{
|
||||
ClutterPaintOperation operation = PAINT_OP_INIT;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
|
||||
g_return_if_fail (coords != NULL);
|
||||
|
||||
clutter_paint_node_maybe_init_operations (node);
|
||||
|
||||
clutter_paint_op_init_tex_rects (&operation, coords, n_rects, FALSE);
|
||||
g_array_append_val (node->operations, operation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_add_primitive: (skip)
|
||||
* @node: a #ClutterPaintNode
|
||||
@ -1154,26 +1058,13 @@ clutter_paint_node_to_json (ClutterPaintNode *node)
|
||||
json_builder_end_array (builder);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
json_builder_set_member_name (builder, "texrects");
|
||||
json_builder_begin_array (builder);
|
||||
|
||||
for (j = 0; i < op->coords->len; j++)
|
||||
{
|
||||
float coord = g_array_index (op->coords, float, j);
|
||||
json_builder_add_double_value (builder, coord);
|
||||
}
|
||||
|
||||
json_builder_end_array (builder);
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
json_builder_set_member_name (builder, "texrect");
|
||||
json_builder_begin_array (builder);
|
||||
|
||||
for (j = 0; i < op->coords->len; j++)
|
||||
for (j = 0; i < op->multitex_coords->len; j++)
|
||||
{
|
||||
float coord = g_array_index (op->coords, float, j);
|
||||
float coord = g_array_index (op->multitex_coords, float, j);
|
||||
json_builder_add_double_value (builder, coord);
|
||||
}
|
||||
|
||||
@ -1258,14 +1149,24 @@ _clutter_paint_node_create (GType gtype)
|
||||
return (gpointer) g_type_create_instance (gtype);
|
||||
}
|
||||
|
||||
static ClutterPaintNode *
|
||||
clutter_paint_node_get_root (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterPaintNode *iter;
|
||||
|
||||
iter = node;
|
||||
while (iter != NULL && iter->parent != NULL)
|
||||
iter = iter->parent;
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_paint_node_get_framebuffer:
|
||||
* @node: a #ClutterPaintNode
|
||||
*
|
||||
* Retrieves the #CoglFramebuffer that @node will draw
|
||||
* into. If @node doesn't specify a custom framebuffer,
|
||||
* the first ancestor with a custom framebuffer will be
|
||||
* used.
|
||||
* into, if it the root node has a custom framebuffer set.
|
||||
*
|
||||
* Returns: (transfer none): a #CoglFramebuffer or %NULL if no custom one is
|
||||
* set.
|
||||
@ -1273,17 +1174,12 @@ _clutter_paint_node_create (GType gtype)
|
||||
CoglFramebuffer *
|
||||
clutter_paint_node_get_framebuffer (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterPaintNode *root = clutter_paint_node_get_root (node);
|
||||
ClutterPaintNodeClass *klass;
|
||||
|
||||
while (node)
|
||||
{
|
||||
klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
|
||||
|
||||
if (klass->get_framebuffer != NULL)
|
||||
return klass->get_framebuffer (node);
|
||||
|
||||
node = node->parent;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
klass = CLUTTER_PAINT_NODE_GET_CLASS (root);
|
||||
if (klass->get_framebuffer != NULL)
|
||||
return klass->get_framebuffer (root);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -83,15 +83,6 @@ void clutter_paint_node_add_multitexture_rectangle (ClutterP
|
||||
const float *text_coords,
|
||||
unsigned int text_coords_len);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_paint_node_add_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_paint_node_add_texture_rectangles (ClutterPaintNode *node,
|
||||
const float *coords,
|
||||
unsigned int n_rects);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_paint_node_add_primitive (ClutterPaintNode *node,
|
||||
CoglPrimitive *primitive);
|
||||
|
@ -33,13 +33,14 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
|
||||
#include "clutter-paint-node-private.h"
|
||||
|
||||
#include <pango/pango.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-blur-private.h"
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
@ -129,7 +130,7 @@ clutter_root_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterRootNode *rnode = (ClutterRootNode *) node;
|
||||
|
||||
g_object_unref (rnode->framebuffer);
|
||||
cogl_object_unref (rnode->framebuffer);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_root_node_parent_class)->finalize (node);
|
||||
}
|
||||
@ -176,7 +177,7 @@ clutter_root_node_new (CoglFramebuffer *framebuffer,
|
||||
clear_color->alpha);
|
||||
cogl_color_premultiply (&res->clear_color);
|
||||
|
||||
res->framebuffer = g_object_ref (framebuffer);
|
||||
res->framebuffer = cogl_object_ref (framebuffer);
|
||||
res->clear_flags = clear_flags;
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
@ -190,7 +191,7 @@ struct _ClutterTransformNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
graphene_matrix_t transform;
|
||||
CoglMatrix transform;
|
||||
};
|
||||
|
||||
struct _ClutterTransformNodeClass
|
||||
@ -237,7 +238,7 @@ clutter_transform_node_class_init (ClutterTransformNodeClass *klass)
|
||||
static void
|
||||
clutter_transform_node_init (ClutterTransformNode *self)
|
||||
{
|
||||
graphene_matrix_init_identity (&self->transform);
|
||||
cogl_matrix_init_identity (&self->transform);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -248,13 +249,13 @@ clutter_transform_node_init (ClutterTransformNode *self)
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_transform_node_new (const graphene_matrix_t *transform)
|
||||
clutter_transform_node_new (const CoglMatrix *transform)
|
||||
{
|
||||
ClutterTransformNode *res;
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_TRANSFORM_NODE);
|
||||
if (transform)
|
||||
graphene_matrix_init_from_matrix (&res->transform, transform);
|
||||
res->transform = *transform;
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
@ -325,7 +326,7 @@ clutter_dummy_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterDummyNode *dnode = (ClutterDummyNode *) node;
|
||||
|
||||
g_clear_object (&dnode->framebuffer);
|
||||
cogl_clear_object (&dnode->framebuffer);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_dummy_node_parent_class)->finalize (node);
|
||||
}
|
||||
@ -357,7 +358,7 @@ _clutter_dummy_node_new (ClutterActor *actor,
|
||||
|
||||
dnode = (ClutterDummyNode *) res;
|
||||
dnode->actor = actor;
|
||||
dnode->framebuffer = g_object_ref (framebuffer);
|
||||
dnode->framebuffer = cogl_object_ref (framebuffer);
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -465,13 +466,6 @@ clutter_pipeline_node_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[7]);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
cogl_framebuffer_draw_textured_rectangles (fb,
|
||||
pnode->pipeline,
|
||||
(float *) op->coords->data,
|
||||
op->coords->len / 8);
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
cogl_framebuffer_draw_multitextured_rectangle (fb,
|
||||
pnode->pipeline,
|
||||
@ -479,8 +473,8 @@ clutter_pipeline_node_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[2],
|
||||
op->op.texrect[3],
|
||||
(float *) op->coords->data,
|
||||
op->coords->len);
|
||||
(float*) op->multitex_coords->data,
|
||||
op->multitex_coords->len);
|
||||
break;
|
||||
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
@ -877,7 +871,6 @@ clutter_text_node_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
case PAINT_OP_INVALID:
|
||||
@ -1039,7 +1032,6 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node,
|
||||
retval = TRUE;
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
case PAINT_OP_INVALID:
|
||||
@ -1074,7 +1066,6 @@ clutter_clip_node_post_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_clip (fb);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
case PAINT_OP_INVALID:
|
||||
@ -1125,7 +1116,7 @@ struct _ClutterActorNode
|
||||
|
||||
ClutterActor *actor;
|
||||
int opacity_override;
|
||||
int saved_opacity_override;
|
||||
int old_opacity_override;
|
||||
};
|
||||
|
||||
struct _ClutterActorNodeClass
|
||||
@ -1143,7 +1134,7 @@ clutter_actor_node_pre_draw (ClutterPaintNode *node,
|
||||
|
||||
if (actor_node->opacity_override != -1)
|
||||
{
|
||||
actor_node->saved_opacity_override =
|
||||
actor_node->old_opacity_override =
|
||||
clutter_actor_get_opacity_override (actor_node->actor);
|
||||
clutter_actor_set_opacity_override (actor_node->actor,
|
||||
actor_node->opacity_override);
|
||||
@ -1174,7 +1165,7 @@ clutter_actor_node_post_draw (ClutterPaintNode *node,
|
||||
if (actor_node->opacity_override != -1)
|
||||
{
|
||||
clutter_actor_set_opacity_override (actor_node->actor,
|
||||
actor_node->saved_opacity_override);
|
||||
actor_node->old_opacity_override);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1306,9 +1297,9 @@ clutter_effect_node_init (ClutterEffectNode *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* clutter_effect_node_new:
|
||||
* @effect: the actor to paint
|
||||
* @actor: the actor to paint
|
||||
*
|
||||
* Creates a new #ClutterEffectNode.
|
||||
*
|
||||
@ -1320,7 +1311,7 @@ clutter_effect_node_new (ClutterEffect *effect)
|
||||
{
|
||||
ClutterEffectNode *res;
|
||||
|
||||
g_assert (CLUTTER_IS_EFFECT (effect));
|
||||
g_assert (effect != NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_EFFECT_NODE);
|
||||
res->effect = effect;
|
||||
@ -1338,7 +1329,7 @@ struct _ClutterLayerNode
|
||||
|
||||
cairo_rectangle_t viewport;
|
||||
|
||||
graphene_matrix_t projection;
|
||||
CoglMatrix projection;
|
||||
|
||||
float fbo_width;
|
||||
float fbo_height;
|
||||
@ -1347,8 +1338,7 @@ struct _ClutterLayerNode
|
||||
CoglFramebuffer *offscreen;
|
||||
|
||||
guint8 opacity;
|
||||
|
||||
gboolean needs_fbo_setup : 1;
|
||||
gboolean update_modelview;
|
||||
};
|
||||
|
||||
struct _ClutterLayerNodeClass
|
||||
@ -1363,8 +1353,6 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterLayerNode *lnode = (ClutterLayerNode *) node;
|
||||
CoglFramebuffer *framebuffer;
|
||||
graphene_matrix_t matrix;
|
||||
|
||||
/* if we were unable to create an offscreen buffer for this node, then
|
||||
* we simply ignore it
|
||||
@ -1372,8 +1360,11 @@ clutter_layer_node_pre_draw (ClutterPaintNode *node,
|
||||
if (lnode->offscreen == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (lnode->needs_fbo_setup)
|
||||
if (lnode->update_modelview)
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglMatrix matrix;
|
||||
|
||||
/* copy the same modelview from the current framebuffer to the one we
|
||||
* are going to use
|
||||
*/
|
||||
@ -1419,7 +1410,8 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
cogl_framebuffer_pop_matrix (lnode->offscreen);
|
||||
clutter_paint_context_pop_framebuffer (paint_context);
|
||||
|
||||
if (!node->operations)
|
||||
/* if no geometry was submitted for this node then we simply ignore it */
|
||||
if (node->operations == NULL)
|
||||
return;
|
||||
|
||||
fb = clutter_paint_context_get_framebuffer (paint_context);
|
||||
@ -1448,13 +1440,6 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[7]);
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
cogl_framebuffer_draw_textured_rectangles (fb,
|
||||
lnode->pipeline,
|
||||
(float *) op->coords->data,
|
||||
op->coords->len / 8);
|
||||
break;
|
||||
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
cogl_framebuffer_draw_multitextured_rectangle (fb,
|
||||
lnode->pipeline,
|
||||
@ -1462,8 +1447,8 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[2],
|
||||
op->op.texrect[3],
|
||||
(float *) op->coords->data,
|
||||
op->coords->len);
|
||||
(float*) op->multitex_coords->data,
|
||||
op->multitex_coords->len);
|
||||
break;
|
||||
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
@ -1483,7 +1468,8 @@ clutter_layer_node_finalize (ClutterPaintNode *node)
|
||||
if (lnode->pipeline != NULL)
|
||||
cogl_object_unref (lnode->pipeline);
|
||||
|
||||
g_clear_object (&lnode->offscreen);
|
||||
if (lnode->offscreen != NULL)
|
||||
cogl_object_unref (lnode->offscreen);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
|
||||
}
|
||||
@ -1522,7 +1508,7 @@ clutter_layer_node_class_init (ClutterLayerNodeClass *klass)
|
||||
static void
|
||||
clutter_layer_node_init (ClutterLayerNode *self)
|
||||
{
|
||||
graphene_matrix_init_identity (&self->projection);
|
||||
cogl_matrix_init_identity (&self->projection);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1545,100 +1531,98 @@ clutter_layer_node_init (ClutterLayerNode *self)
|
||||
* Since: 1.10
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_layer_node_new (const graphene_matrix_t *projection,
|
||||
clutter_layer_node_new (const CoglMatrix *projection,
|
||||
const cairo_rectangle_t *viewport,
|
||||
float width,
|
||||
float height,
|
||||
guint8 opacity)
|
||||
{
|
||||
ClutterLayerNode *lnode;
|
||||
ClutterLayerNode *res;
|
||||
CoglContext *context;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglTexture *texture;
|
||||
CoglColor color;
|
||||
g_autoptr (CoglOffscreen) offscreen = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
lnode = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
|
||||
lnode->needs_fbo_setup = TRUE;
|
||||
lnode->projection = *projection;
|
||||
lnode->viewport = *viewport;
|
||||
lnode->fbo_width = width;
|
||||
lnode->fbo_height = height;
|
||||
lnode->opacity = opacity;
|
||||
res->update_modelview = TRUE;
|
||||
res->projection = *projection;
|
||||
res->viewport = *viewport;
|
||||
res->fbo_width = width;
|
||||
res->fbo_height = height;
|
||||
res->opacity = opacity;
|
||||
|
||||
/* the texture backing the FBO */
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
tex_2d = cogl_texture_2d_new_with_size (context,
|
||||
MAX (lnode->fbo_width, 1),
|
||||
MAX (lnode->fbo_height, 1));
|
||||
MAX (res->fbo_width, 1),
|
||||
MAX (res->fbo_height, 1));
|
||||
texture = COGL_TEXTURE (tex_2d);
|
||||
cogl_texture_set_premultiplied (texture, TRUE);
|
||||
|
||||
offscreen = cogl_offscreen_new_with_texture (texture);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
|
||||
res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture));
|
||||
if (res->offscreen == NULL)
|
||||
{
|
||||
g_warning ("Unable to create an allocate paint node offscreen: %s",
|
||||
error->message);
|
||||
cogl_object_unref (texture);
|
||||
return NULL;
|
||||
g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC);
|
||||
goto out;
|
||||
}
|
||||
|
||||
lnode->offscreen = COGL_FRAMEBUFFER (g_steal_pointer (&offscreen));
|
||||
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
|
||||
/* the pipeline used to paint the texture; we use nearest
|
||||
* interpolation filters because the texture is always
|
||||
* going to be painted at a 1:1 texel:pixel ratio
|
||||
*/
|
||||
lnode->pipeline = cogl_pipeline_copy (default_texture_pipeline);
|
||||
cogl_pipeline_set_layer_filters (lnode->pipeline, 0,
|
||||
res->pipeline = cogl_pipeline_copy (default_texture_pipeline);
|
||||
cogl_pipeline_set_layer_filters (res->pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (lnode->pipeline, 0, texture);
|
||||
cogl_pipeline_set_color (lnode->pipeline, &color);
|
||||
cogl_pipeline_set_layer_texture (res->pipeline, 0, texture);
|
||||
cogl_pipeline_set_color (res->pipeline, &color);
|
||||
|
||||
out:
|
||||
cogl_object_unref (texture);
|
||||
|
||||
return (ClutterPaintNode *) lnode;
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layer_node_new_to_framebuffer:
|
||||
* clutter_layer_node_new_with_framebuffer:
|
||||
* @framebuffer: a #CoglFramebuffer
|
||||
* @pipeline: a #CoglPipeline
|
||||
* @opacity: the opacity to be used when drawing the layer
|
||||
*
|
||||
* Creates a new #ClutterLayerNode that will redirect drawing at
|
||||
* @framebuffer. It will then use @pipeline to paint the stored
|
||||
* operations.
|
||||
* Creates a new #ClutterLayerNode with @framebuffer and
|
||||
* @pipeline. @framebuffer will then be painted using the
|
||||
* given @opacity.
|
||||
*
|
||||
* When using this constructor, the caller is reponsible for setting
|
||||
* up @framebuffer, including its modelview and projection matrices,
|
||||
* and the viewport, and the @pipeline as well.
|
||||
* When using this constructor, the caller is responsible
|
||||
* for setting up the framebuffer's modelview and projection
|
||||
* matrices.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterLayerNode.
|
||||
* Return value: (transfer full)(nullable): the newly created #ClutterLayerNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_layer_node_new_to_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline)
|
||||
clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
guint8 opacity)
|
||||
{
|
||||
ClutterLayerNode *res;
|
||||
CoglColor color;
|
||||
|
||||
g_return_val_if_fail (COGL_IS_FRAMEBUFFER (framebuffer), NULL);
|
||||
g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
|
||||
g_return_val_if_fail (cogl_is_framebuffer (framebuffer), NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
|
||||
|
||||
res->needs_fbo_setup = FALSE;
|
||||
res->fbo_width = cogl_framebuffer_get_width (framebuffer);
|
||||
res->fbo_height = cogl_framebuffer_get_height (framebuffer);
|
||||
res->offscreen = g_object_ref (framebuffer);
|
||||
res->update_modelview = FALSE;
|
||||
res->offscreen = cogl_object_ref (framebuffer);
|
||||
res->pipeline = cogl_pipeline_copy (pipeline);
|
||||
|
||||
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
|
||||
cogl_pipeline_set_color (res->pipeline, &color);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
|
||||
@ -1650,7 +1634,13 @@ struct _ClutterBlitNode
|
||||
{
|
||||
ClutterPaintNode parent_instance;
|
||||
|
||||
CoglFramebuffer *src;
|
||||
CoglFramebuffer *source;
|
||||
CoglFramebuffer *dest;
|
||||
};
|
||||
|
||||
struct _ClutterBlitNodeClass
|
||||
{
|
||||
ClutterPaintNodeClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterBlitNode, clutter_blit_node, CLUTTER_TYPE_PAINT_NODE)
|
||||
@ -1668,13 +1658,15 @@ clutter_blit_node_draw (ClutterPaintNode *node,
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
g_autoptr (GError) error = NULL;
|
||||
CoglFramebuffer *framebuffer;
|
||||
unsigned int i;
|
||||
CoglFramebuffer *source;
|
||||
guint i;
|
||||
|
||||
if (node->operations == NULL)
|
||||
return;
|
||||
|
||||
framebuffer = get_target_framebuffer (node, paint_context);
|
||||
source = blit_node->source;
|
||||
if (!source)
|
||||
source = clutter_paint_context_get_framebuffer (paint_context);
|
||||
|
||||
for (i = 0; i < node->operations->len; i++)
|
||||
{
|
||||
@ -1692,8 +1684,8 @@ clutter_blit_node_draw (ClutterPaintNode *node,
|
||||
op_width = op->op.texrect[6] - op->op.texrect[4];
|
||||
op_height = op->op.texrect[7] - op->op.texrect[5];
|
||||
|
||||
cogl_blit_framebuffer (blit_node->src,
|
||||
framebuffer,
|
||||
cogl_blit_framebuffer (source,
|
||||
blit_node->dest,
|
||||
op->op.texrect[0],
|
||||
op->op.texrect[1],
|
||||
op->op.texrect[4],
|
||||
@ -1709,7 +1701,6 @@ clutter_blit_node_draw (ClutterPaintNode *node,
|
||||
}
|
||||
break;
|
||||
|
||||
case PAINT_OP_TEX_RECTS:
|
||||
case PAINT_OP_MULTITEX_RECT:
|
||||
case PAINT_OP_PRIMITIVE:
|
||||
break;
|
||||
@ -1722,9 +1713,10 @@ clutter_blit_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
|
||||
g_clear_object (&blit_node->src);
|
||||
cogl_clear_object (&blit_node->source);
|
||||
cogl_clear_object (&blit_node->dest);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_blit_node_parent_class)->finalize (node);
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_layer_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
@ -1732,21 +1724,29 @@ clutter_blit_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlitNode *blit_node = CLUTTER_BLIT_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *src_ptr = NULL;
|
||||
|
||||
src_ptr = g_strdup_printf ("%p", blit_node->src);
|
||||
g_autofree char *source_ptr = NULL;
|
||||
g_autofree char *dest_ptr = NULL;
|
||||
|
||||
builder = json_builder_new ();
|
||||
|
||||
source_ptr = g_strdup_printf ("%p", blit_node->source);
|
||||
dest_ptr = g_strdup_printf ("%p", blit_node->dest);
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "source");
|
||||
json_builder_add_string_value (builder, src_ptr);
|
||||
json_builder_add_string_value (builder, source_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "dest");
|
||||
json_builder_add_string_value (builder, dest_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blit_node_class_init (ClutterBlitNodeClass *klass)
|
||||
clutter_blit_node_class_init (ClutterTransformNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
@ -1764,10 +1764,13 @@ clutter_blit_node_init (ClutterBlitNode *self)
|
||||
|
||||
/**
|
||||
* clutter_blit_node_new:
|
||||
* @src: the source #CoglFramebuffer
|
||||
* @source: (nullable): the source #CoglFramebuffer
|
||||
* @dest: the destination #CoglFramebuffer
|
||||
*
|
||||
* Creates a new #ClutterBlitNode that blits @src into the current
|
||||
* draw framebuffer.
|
||||
* Creates a new #ClutterBlitNode that blits @source into @dest.
|
||||
*
|
||||
* If @source is %NULL, the most recent framebuffer stacked into a
|
||||
* #ClutterPaintContext is used.
|
||||
*
|
||||
* You must only add rectangles using clutter_blit_node_add_blit_rectangle().
|
||||
*
|
||||
@ -1775,14 +1778,16 @@ clutter_blit_node_init (ClutterBlitNode *self)
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_blit_node_new (CoglFramebuffer *src)
|
||||
clutter_blit_node_new (CoglFramebuffer *source,
|
||||
CoglFramebuffer *dest)
|
||||
{
|
||||
ClutterBlitNode *res;
|
||||
|
||||
g_return_val_if_fail (COGL_IS_FRAMEBUFFER (src), NULL);
|
||||
g_return_val_if_fail (cogl_is_framebuffer (dest), NULL);
|
||||
|
||||
res = _clutter_paint_node_create (CLUTTER_TYPE_BLIT_NODE);
|
||||
res->src = g_object_ref (src);
|
||||
res->source = source ? cogl_object_ref (source) : NULL;
|
||||
res->dest = cogl_object_ref (dest);
|
||||
|
||||
return (ClutterPaintNode *) res;
|
||||
}
|
||||
@ -1813,159 +1818,13 @@ clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
|
||||
clutter_paint_node_add_texture_rectangle (CLUTTER_PAINT_NODE (blit_node),
|
||||
&(ClutterActorBox) {
|
||||
.x1 = src_x,
|
||||
.y1 = src_y,
|
||||
.x2 = src_x + width,
|
||||
.y2 = src_y + height,
|
||||
src_x,
|
||||
src_y,
|
||||
src_x + width,
|
||||
src_y + height,
|
||||
},
|
||||
dst_x,
|
||||
dst_y,
|
||||
dst_x + width,
|
||||
dst_y + height);
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterBlurNode
|
||||
*/
|
||||
|
||||
struct _ClutterBlurNode
|
||||
{
|
||||
ClutterLayerNode parent_instance;
|
||||
|
||||
ClutterBlur *blur;
|
||||
unsigned int sigma;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterBlurNode, clutter_blur_node, CLUTTER_TYPE_LAYER_NODE)
|
||||
|
||||
static void
|
||||
clutter_blur_node_post_draw (ClutterPaintNode *node,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterPaintNodeClass *parent_class =
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_blur_node_parent_class);
|
||||
ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
|
||||
|
||||
clutter_blur_apply (blur_node->blur);
|
||||
|
||||
parent_class->post_draw (node, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_node_finalize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
|
||||
|
||||
g_clear_pointer (&blur_node->blur, clutter_blur_free);
|
||||
|
||||
CLUTTER_PAINT_NODE_CLASS (clutter_blur_node_parent_class)->finalize (node);
|
||||
}
|
||||
|
||||
static JsonNode *
|
||||
clutter_blur_node_serialize (ClutterPaintNode *node)
|
||||
{
|
||||
ClutterBlurNode *blur_node = CLUTTER_BLUR_NODE (node);
|
||||
g_autoptr (JsonBuilder) builder = NULL;
|
||||
g_autofree char *src_ptr = NULL;
|
||||
|
||||
src_ptr = g_strdup_printf ("%d", blur_node->sigma);
|
||||
|
||||
builder = json_builder_new ();
|
||||
json_builder_begin_object (builder);
|
||||
json_builder_set_member_name (builder, "sigma");
|
||||
json_builder_add_string_value (builder, src_ptr);
|
||||
json_builder_end_object (builder);
|
||||
|
||||
return json_builder_get_root (builder);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_node_class_init (ClutterBlurNodeClass *klass)
|
||||
{
|
||||
ClutterPaintNodeClass *node_class;
|
||||
|
||||
node_class = CLUTTER_PAINT_NODE_CLASS (klass);
|
||||
node_class->post_draw = clutter_blur_node_post_draw;
|
||||
node_class->finalize = clutter_blur_node_finalize;
|
||||
node_class->serialize = clutter_blur_node_serialize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_blur_node_init (ClutterBlurNode *blur_node)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_blur_node_new:
|
||||
* @width width of the blur layer
|
||||
* @height: height of the blur layer
|
||||
* @sigma: sigma value of the blur
|
||||
*
|
||||
* Creates a new #ClutterBlurNode.
|
||||
*
|
||||
* Children of this node will be painted inside a separate framebuffer,
|
||||
* which will be blurred and painted on the current draw framebuffer.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterBlurNode.
|
||||
* Use clutter_paint_node_unref() when done.
|
||||
*/
|
||||
ClutterPaintNode *
|
||||
clutter_blur_node_new (unsigned int width,
|
||||
unsigned int height,
|
||||
float sigma)
|
||||
{
|
||||
g_autoptr (CoglOffscreen) offscreen = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
ClutterLayerNode *layer_node;
|
||||
ClutterBlurNode *blur_node;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglContext *context;
|
||||
CoglTexture *texture;
|
||||
ClutterBlur *blur;
|
||||
|
||||
g_return_val_if_fail (sigma >= 0.0, NULL);
|
||||
|
||||
blur_node = _clutter_paint_node_create (CLUTTER_TYPE_BLUR_NODE);
|
||||
blur_node->sigma = sigma;
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
tex_2d = cogl_texture_2d_new_with_size (context, width, height);
|
||||
|
||||
texture = COGL_TEXTURE (tex_2d);
|
||||
cogl_texture_set_premultiplied (texture, TRUE);
|
||||
|
||||
offscreen = cogl_offscreen_new_with_texture (texture);
|
||||
cogl_object_unref (tex_2d);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
|
||||
{
|
||||
g_warning ("Unable to allocate paint node offscreen: %s",
|
||||
error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
blur = clutter_blur_new (texture, sigma);
|
||||
blur_node->blur = blur;
|
||||
|
||||
if (!blur)
|
||||
{
|
||||
g_warning ("Failed to create blur pipeline");
|
||||
goto out;
|
||||
}
|
||||
|
||||
layer_node = CLUTTER_LAYER_NODE (blur_node);
|
||||
layer_node->offscreen = COGL_FRAMEBUFFER (g_steal_pointer (&offscreen));
|
||||
layer_node->pipeline = cogl_pipeline_copy (default_texture_pipeline);
|
||||
cogl_pipeline_set_layer_filters (layer_node->pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_LINEAR,
|
||||
COGL_PIPELINE_FILTER_LINEAR);
|
||||
cogl_pipeline_set_layer_texture (layer_node->pipeline,
|
||||
0,
|
||||
clutter_blur_get_texture (blur));
|
||||
|
||||
cogl_framebuffer_orthographic (layer_node->offscreen,
|
||||
0.0, 0.0,
|
||||
width, height,
|
||||
0.0, 1.0);
|
||||
|
||||
out:
|
||||
return (ClutterPaintNode *) blur_node;
|
||||
}
|
||||
|
@ -203,15 +203,16 @@ CLUTTER_EXPORT
|
||||
GType clutter_layer_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_layer_node_new (const graphene_matrix_t *projection,
|
||||
ClutterPaintNode * clutter_layer_node_new (const CoglMatrix *projection,
|
||||
const cairo_rectangle_t *viewport,
|
||||
float width,
|
||||
float height,
|
||||
guint8 opacity);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_layer_node_new_to_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline);
|
||||
ClutterPaintNode * clutter_layer_node_new_with_framebuffer (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
guint8 opacity);
|
||||
|
||||
|
||||
#define CLUTTER_TYPE_TRANSFORM_NODE (clutter_transform_node_get_type ())
|
||||
@ -233,7 +234,7 @@ CLUTTER_EXPORT
|
||||
GType clutter_transform_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_transform_node_new (const graphene_matrix_t *projection);
|
||||
ClutterPaintNode * clutter_transform_node_new (const CoglMatrix *projection);
|
||||
|
||||
#define CLUTTER_TYPE_BLIT_NODE (clutter_blit_node_get_type ())
|
||||
#define CLUTTER_BLIT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLIT_NODE, ClutterBlitNode))
|
||||
@ -242,8 +243,10 @@ ClutterPaintNode * clutter_transform_node_new (const graphene_matr
|
||||
/*
|
||||
* ClutterBlitNode:
|
||||
*
|
||||
* The #ClutterBlitNode structure is an opaque
|
||||
* The #ClutterLayerNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*
|
||||
* Since: 1.10
|
||||
*/
|
||||
typedef struct _ClutterBlitNode ClutterBlitNode;
|
||||
typedef struct _ClutterPaintNodeClass ClutterBlitNodeClass;
|
||||
@ -252,7 +255,9 @@ CLUTTER_EXPORT
|
||||
GType clutter_blit_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_blit_node_new (CoglFramebuffer *src);
|
||||
ClutterPaintNode * clutter_blit_node_new (CoglFramebuffer *source,
|
||||
CoglFramebuffer *dest);
|
||||
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
@ -263,27 +268,6 @@ void clutter_blit_node_add_blit_rectangle (ClutterBlitNode *blit_node,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
#define CLUTTER_TYPE_BLUR_NODE (clutter_blur_node_get_type ())
|
||||
#define CLUTTER_BLUR_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BLUR_NODE, ClutterBlurNode))
|
||||
#define CLUTTER_IS_BLUR_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BLUR_NODE))
|
||||
|
||||
/**
|
||||
* ClutterBlurNode:
|
||||
*
|
||||
* The #ClutterBurNode structure is an opaque
|
||||
* type whose members cannot be directly accessed.
|
||||
*/
|
||||
typedef struct _ClutterBlurNode ClutterBlurNode;
|
||||
typedef struct _ClutterLayerNodeClass ClutterBlurNodeClass;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_blur_node_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPaintNode * clutter_blur_node_new (unsigned int width,
|
||||
unsigned int height,
|
||||
float sigma);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PAINT_NODES_H__ */
|
||||
|
@ -62,7 +62,7 @@ struct _ClutterPaintVolume
|
||||
|
||||
/* As an optimization for internally managed PaintVolumes we allow
|
||||
* initializing ClutterPaintVolume variables allocated on the stack
|
||||
* so we can avoid hammering the memory allocator. */
|
||||
* so we can avoid hammering the slice allocator. */
|
||||
guint is_static:1;
|
||||
|
||||
/* A newly initialized PaintVolume is considered empty as it is
|
||||
@ -85,8 +85,8 @@ struct _ClutterPaintVolume
|
||||
* TRUE) */
|
||||
guint is_2d:1;
|
||||
|
||||
/* Set to TRUE initially but cleared if the paint volume is
|
||||
* transformed by a matrix. */
|
||||
/* Set to TRUE initialy but cleared if the paint volume is
|
||||
* transfomed by a matrix. */
|
||||
guint is_axis_aligned:1;
|
||||
|
||||
|
||||
@ -111,20 +111,20 @@ void _clutter_paint_volume_set_from_volume (ClutterPaintVolu
|
||||
const ClutterPaintVolume *src);
|
||||
|
||||
void _clutter_paint_volume_complete (ClutterPaintVolume *pv);
|
||||
void _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *matrix);
|
||||
void _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection,
|
||||
const float *viewport);
|
||||
void _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
const CoglMatrix *matrix);
|
||||
void _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport);
|
||||
void _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv,
|
||||
ClutterActorBox *box);
|
||||
void _clutter_paint_volume_axis_align (ClutterPaintVolume *pv);
|
||||
void _clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv,
|
||||
ClutterActor *actor);
|
||||
|
||||
ClutterCullResult _clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const graphene_frustum_t *frustum);
|
||||
ClutterCullResult _clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const ClutterPlane *planes);
|
||||
|
||||
void _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
|
||||
ClutterStage *stage,
|
||||
@ -133,9 +133,6 @@ void _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolu
|
||||
void _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
|
||||
ClutterActor *relative_to_ancestor);
|
||||
|
||||
void clutter_paint_volume_to_box (ClutterPaintVolume *pv,
|
||||
graphene_box_t *box);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PAINT_VOLUME_PRIVATE_H__ */
|
||||
|
@ -59,7 +59,7 @@ _clutter_paint_volume_new (ClutterActor *actor)
|
||||
|
||||
g_return_val_if_fail (actor != NULL, NULL);
|
||||
|
||||
pv = g_new0 (ClutterPaintVolume, 1);
|
||||
pv = g_slice_new (ClutterPaintVolume);
|
||||
|
||||
pv->actor = actor;
|
||||
|
||||
@ -78,7 +78,7 @@ _clutter_paint_volume_new (ClutterActor *actor)
|
||||
* traversal of a Clutter scene graph and since paint volumes often
|
||||
* have a very short life cycle that maps well to stack allocation we
|
||||
* allow initializing a static ClutterPaintVolume variable to avoid
|
||||
* hammering the memory allocator.
|
||||
* hammering the slice allocator.
|
||||
*
|
||||
* We were seeing slice allocation take about 1% cumulative CPU time
|
||||
* for some very simple clutter tests which although it isn't a *lot*
|
||||
@ -133,7 +133,7 @@ clutter_paint_volume_copy (const ClutterPaintVolume *pv)
|
||||
|
||||
g_return_val_if_fail (pv != NULL, NULL);
|
||||
|
||||
copy = g_memdup2 (pv, sizeof (ClutterPaintVolume));
|
||||
copy = g_slice_dup (ClutterPaintVolume, pv);
|
||||
copy->is_static = FALSE;
|
||||
|
||||
return copy;
|
||||
@ -164,7 +164,7 @@ clutter_paint_volume_free (ClutterPaintVolume *pv)
|
||||
if (G_LIKELY (pv->is_static))
|
||||
return;
|
||||
|
||||
g_free (pv);
|
||||
g_slice_free (ClutterPaintVolume, pv);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -533,11 +533,6 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
|
||||
const ClutterPaintVolume *another_pv)
|
||||
{
|
||||
ClutterPaintVolume aligned_pv;
|
||||
graphene_point3d_t min;
|
||||
graphene_point3d_t max;
|
||||
graphene_box_t another_box;
|
||||
graphene_box_t union_box;
|
||||
graphene_box_t box;
|
||||
|
||||
g_return_if_fail (pv != NULL);
|
||||
g_return_if_fail (another_pv != NULL);
|
||||
@ -545,6 +540,9 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
|
||||
/* Both volumes have to belong to the same local coordinate space */
|
||||
g_return_if_fail (pv->actor == another_pv->actor);
|
||||
|
||||
/* NB: we only have to update vertices 0, 1, 3 and 4
|
||||
* (See the ClutterPaintVolume typedef for more details) */
|
||||
|
||||
/* We special case empty volumes because otherwise we'd end up
|
||||
* calculating a bounding box that would enclose the origin of
|
||||
* the empty volume which isn't desired.
|
||||
@ -561,34 +559,78 @@ clutter_paint_volume_union (ClutterPaintVolume *pv,
|
||||
if (!pv->is_axis_aligned)
|
||||
_clutter_paint_volume_axis_align (pv);
|
||||
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
if (!another_pv->is_axis_aligned || !another_pv->is_complete)
|
||||
if (!another_pv->is_axis_aligned)
|
||||
{
|
||||
_clutter_paint_volume_copy_static (another_pv, &aligned_pv);
|
||||
_clutter_paint_volume_axis_align (&aligned_pv);
|
||||
_clutter_paint_volume_complete (&aligned_pv);
|
||||
another_pv = &aligned_pv;
|
||||
}
|
||||
|
||||
if (G_LIKELY (pv->is_2d))
|
||||
graphene_box_init_from_points (&box, 4, pv->vertices);
|
||||
else
|
||||
graphene_box_init_from_points (&box, 8, pv->vertices);
|
||||
/* grow left*/
|
||||
/* left vertices 0, 3, 4, 7 */
|
||||
if (another_pv->vertices[0].x < pv->vertices[0].x)
|
||||
{
|
||||
int min_x = another_pv->vertices[0].x;
|
||||
pv->vertices[0].x = min_x;
|
||||
pv->vertices[3].x = min_x;
|
||||
pv->vertices[4].x = min_x;
|
||||
/* pv->vertices[7].x = min_x; */
|
||||
}
|
||||
|
||||
if (G_LIKELY (another_pv->is_2d))
|
||||
graphene_box_init_from_points (&another_box, 4, another_pv->vertices);
|
||||
else
|
||||
graphene_box_init_from_points (&another_box, 8, another_pv->vertices);
|
||||
/* grow right */
|
||||
/* right vertices 1, 2, 5, 6 */
|
||||
if (another_pv->vertices[1].x > pv->vertices[1].x)
|
||||
{
|
||||
int max_x = another_pv->vertices[1].x;
|
||||
pv->vertices[1].x = max_x;
|
||||
/* pv->vertices[2].x = max_x; */
|
||||
/* pv->vertices[5].x = max_x; */
|
||||
/* pv->vertices[6].x = max_x; */
|
||||
}
|
||||
|
||||
graphene_box_union (&box, &another_box, &union_box);
|
||||
/* grow up */
|
||||
/* top vertices 0, 1, 4, 5 */
|
||||
if (another_pv->vertices[0].y < pv->vertices[0].y)
|
||||
{
|
||||
int min_y = another_pv->vertices[0].y;
|
||||
pv->vertices[0].y = min_y;
|
||||
pv->vertices[1].y = min_y;
|
||||
pv->vertices[4].y = min_y;
|
||||
/* pv->vertices[5].y = min_y; */
|
||||
}
|
||||
|
||||
graphene_box_get_min (&union_box, &min);
|
||||
graphene_box_get_max (&union_box, &max);
|
||||
graphene_point3d_init (&pv->vertices[0], min.x, min.y, min.z);
|
||||
graphene_point3d_init (&pv->vertices[1], max.x, min.y, min.z);
|
||||
graphene_point3d_init (&pv->vertices[3], min.x, max.y, min.z);
|
||||
graphene_point3d_init (&pv->vertices[4], min.x, min.y, max.z);
|
||||
/* grow down */
|
||||
/* bottom vertices 2, 3, 6, 7 */
|
||||
if (another_pv->vertices[3].y > pv->vertices[3].y)
|
||||
{
|
||||
int may_y = another_pv->vertices[3].y;
|
||||
/* pv->vertices[2].y = may_y; */
|
||||
pv->vertices[3].y = may_y;
|
||||
/* pv->vertices[6].y = may_y; */
|
||||
/* pv->vertices[7].y = may_y; */
|
||||
}
|
||||
|
||||
/* grow forward */
|
||||
/* front vertices 0, 1, 2, 3 */
|
||||
if (another_pv->vertices[0].z < pv->vertices[0].z)
|
||||
{
|
||||
int min_z = another_pv->vertices[0].z;
|
||||
pv->vertices[0].z = min_z;
|
||||
pv->vertices[1].z = min_z;
|
||||
/* pv->vertices[2].z = min_z; */
|
||||
pv->vertices[3].z = min_z;
|
||||
}
|
||||
|
||||
/* grow backward */
|
||||
/* back vertices 4, 5, 6, 7 */
|
||||
if (another_pv->vertices[4].z > pv->vertices[4].z)
|
||||
{
|
||||
int maz_z = another_pv->vertices[4].z;
|
||||
pv->vertices[4].z = maz_z;
|
||||
/* pv->vertices[5].z = maz_z; */
|
||||
/* pv->vertices[6].z = maz_z; */
|
||||
/* pv->vertices[7].z = maz_z; */
|
||||
}
|
||||
|
||||
if (pv->vertices[4].z == pv->vertices[0].z)
|
||||
pv->is_2d = TRUE;
|
||||
@ -766,8 +808,8 @@ _clutter_paint_volume_get_bounding_box (ClutterPaintVolume *pv,
|
||||
|
||||
void
|
||||
_clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection,
|
||||
const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport)
|
||||
{
|
||||
int transform_count;
|
||||
@ -785,7 +827,7 @@ _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
}
|
||||
|
||||
/* All the vertices must be up to date, since after the projection
|
||||
* it won't be trivial to derive the other vertices. */
|
||||
* it wont be trivial to derive the other vertices. */
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
/* Most actors are 2D so we only have to transform the front 4
|
||||
@ -807,7 +849,7 @@ _clutter_paint_volume_project (ClutterPaintVolume *pv,
|
||||
|
||||
void
|
||||
_clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
const graphene_matrix_t *matrix)
|
||||
const CoglMatrix *matrix)
|
||||
{
|
||||
int transform_count;
|
||||
|
||||
@ -815,16 +857,16 @@ _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
{
|
||||
gfloat w = 1;
|
||||
/* Just transform the origin */
|
||||
cogl_graphene_matrix_project_point (matrix,
|
||||
&pv->vertices[0].x,
|
||||
&pv->vertices[0].y,
|
||||
&pv->vertices[0].z,
|
||||
&w);
|
||||
cogl_matrix_transform_point (matrix,
|
||||
&pv->vertices[0].x,
|
||||
&pv->vertices[0].y,
|
||||
&pv->vertices[0].z,
|
||||
&w);
|
||||
return;
|
||||
}
|
||||
|
||||
/* All the vertices must be up to date, since after the transform
|
||||
* it won't be trivial to derive the other vertices. */
|
||||
* it wont be trivial to derive the other vertices. */
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
/* Most actors are 2D so we only have to transform the front 4
|
||||
@ -834,13 +876,13 @@ _clutter_paint_volume_transform (ClutterPaintVolume *pv,
|
||||
else
|
||||
transform_count = 8;
|
||||
|
||||
cogl_graphene_matrix_transform_points (matrix,
|
||||
3,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
transform_count);
|
||||
cogl_matrix_transform_points (matrix,
|
||||
3,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
sizeof (graphene_point3d_t),
|
||||
pv->vertices,
|
||||
transform_count);
|
||||
|
||||
pv->is_axis_aligned = FALSE;
|
||||
}
|
||||
@ -1015,9 +1057,9 @@ clutter_paint_volume_set_from_allocation (ClutterPaintVolume *pv,
|
||||
}
|
||||
|
||||
/* Currently paint volumes are defined relative to a given actor, but
|
||||
* in some cases it is desirable to be able to change the actor that
|
||||
* in some cases it is desireable to be able to change the actor that
|
||||
* a volume relates too (For instance for ClutterClone actors where we
|
||||
* need to masquerade the source actors volume as the volume for the
|
||||
* need to masquarade the source actors volume as the volume for the
|
||||
* clone). */
|
||||
void
|
||||
_clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv,
|
||||
@ -1029,11 +1071,14 @@ _clutter_paint_volume_set_reference_actor (ClutterPaintVolume *pv,
|
||||
}
|
||||
|
||||
ClutterCullResult
|
||||
_clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const graphene_frustum_t *frustum)
|
||||
_clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
const ClutterPlane *planes)
|
||||
{
|
||||
int vertex_count;
|
||||
graphene_box_t box;
|
||||
graphene_point3d_t *vertices = pv->vertices;
|
||||
gboolean partial = FALSE;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
if (pv->is_empty)
|
||||
return CLUTTER_CULL_RESULT_OUT;
|
||||
@ -1050,12 +1095,33 @@ _clutter_paint_volume_cull (ClutterPaintVolume *pv,
|
||||
else
|
||||
vertex_count = 8;
|
||||
|
||||
graphene_box_init_from_points (&box, vertex_count, pv->vertices);
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
const ClutterPlane *plane = &planes[i];
|
||||
int out = 0;
|
||||
for (j = 0; j < vertex_count; j++)
|
||||
{
|
||||
graphene_vec3_t v;
|
||||
|
||||
if (graphene_frustum_intersects_box (frustum, &box))
|
||||
return CLUTTER_CULL_RESULT_IN;
|
||||
graphene_vec3_init (&v,
|
||||
vertices[j].x - graphene_vec3_get_x (&plane->v0),
|
||||
vertices[j].y - graphene_vec3_get_y (&plane->v0),
|
||||
vertices[j].z - graphene_vec3_get_z (&plane->v0));
|
||||
|
||||
if (graphene_vec3_dot (&plane->n, &v) < 0)
|
||||
out++;
|
||||
}
|
||||
|
||||
if (out == vertex_count)
|
||||
return CLUTTER_CULL_RESULT_OUT;
|
||||
else if (out != 0)
|
||||
partial = TRUE;
|
||||
}
|
||||
|
||||
if (partial)
|
||||
return CLUTTER_CULL_RESULT_PARTIAL;
|
||||
else
|
||||
return CLUTTER_CULL_RESULT_OUT;
|
||||
return CLUTTER_CULL_RESULT_IN;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1064,13 +1130,13 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
|
||||
ClutterActorBox *box)
|
||||
{
|
||||
ClutterPaintVolume projected_pv;
|
||||
graphene_matrix_t modelview;
|
||||
graphene_matrix_t projection;
|
||||
CoglMatrix modelview;
|
||||
CoglMatrix projection;
|
||||
float viewport[4];
|
||||
|
||||
_clutter_paint_volume_copy_static (pv, &projected_pv);
|
||||
|
||||
graphene_matrix_init_identity (&modelview);
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
|
||||
/* If the paint volume isn't already in eye coordinates... */
|
||||
if (pv->actor)
|
||||
@ -1115,7 +1181,7 @@ void
|
||||
_clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
|
||||
ClutterActor *relative_to_ancestor)
|
||||
{
|
||||
graphene_matrix_t matrix;
|
||||
CoglMatrix matrix;
|
||||
ClutterActor *actor;
|
||||
|
||||
actor = pv->actor;
|
||||
@ -1124,32 +1190,10 @@ _clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
|
||||
|
||||
_clutter_paint_volume_set_reference_actor (pv, relative_to_ancestor);
|
||||
|
||||
graphene_matrix_init_identity (&matrix);
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
_clutter_actor_apply_relative_transformation_matrix (actor,
|
||||
relative_to_ancestor,
|
||||
&matrix);
|
||||
|
||||
_clutter_paint_volume_transform (pv, &matrix);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_paint_volume_to_box (ClutterPaintVolume *pv,
|
||||
graphene_box_t *box)
|
||||
{
|
||||
int vertex_count;
|
||||
|
||||
if (pv->is_empty)
|
||||
{
|
||||
graphene_box_init_from_box (box, graphene_box_empty ());
|
||||
return;
|
||||
}
|
||||
|
||||
_clutter_paint_volume_complete (pv);
|
||||
|
||||
if (G_LIKELY (pv->is_2d))
|
||||
vertex_count = 4;
|
||||
else
|
||||
vertex_count = 8;
|
||||
|
||||
graphene_box_init_from_points (box, vertex_count, pv->vertices);
|
||||
}
|
||||
|
@ -354,15 +354,12 @@ clutter_pan_action_real_pan (ClutterPanAction *self,
|
||||
gboolean is_interpolated)
|
||||
{
|
||||
gfloat dx, dy;
|
||||
graphene_matrix_t transform;
|
||||
graphene_matrix_t translate;
|
||||
ClutterMatrix transform;
|
||||
|
||||
clutter_pan_action_get_constrained_motion_delta (self, 0, &dx, &dy);
|
||||
|
||||
clutter_actor_get_child_transform (actor, &transform);
|
||||
graphene_matrix_init_translate (&translate,
|
||||
&GRAPHENE_POINT3D_INIT (dx, dy, 0.0f));
|
||||
graphene_matrix_multiply (&translate, &transform, &transform);
|
||||
cogl_matrix_translate (&transform, dx, dy, 0.0f);
|
||||
clutter_actor_set_child_transform (actor, &transform);
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ clutter_path_add_node_full (ClutterPath *path,
|
||||
priv->nodes_dirty = TRUE;
|
||||
}
|
||||
|
||||
/* Helper function to make the rest of the add_* functions shorter */
|
||||
/* Helper function to make the rest of teh add_* functions shorter */
|
||||
static void
|
||||
clutter_path_add_node_helper (ClutterPath *path,
|
||||
ClutterPathNodeType type,
|
||||
@ -1446,7 +1446,7 @@ clutter_path_get_length (ClutterPath *path)
|
||||
static ClutterPathNodeFull *
|
||||
clutter_path_node_full_new (void)
|
||||
{
|
||||
return g_new0 (ClutterPathNodeFull, 1);
|
||||
return g_slice_new0 (ClutterPathNodeFull);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1455,7 +1455,7 @@ clutter_path_node_full_free (ClutterPathNodeFull *node)
|
||||
if (node->bezier)
|
||||
_clutter_bezier_free (node->bezier);
|
||||
|
||||
g_free (node);
|
||||
g_slice_free (ClutterPathNodeFull, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1471,7 +1471,7 @@ clutter_path_node_full_free (ClutterPathNodeFull *node)
|
||||
ClutterPathNode *
|
||||
clutter_path_node_copy (const ClutterPathNode *node)
|
||||
{
|
||||
return g_memdup2 (node, sizeof (ClutterPathNode));
|
||||
return g_slice_dup (ClutterPathNode, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1486,7 +1486,7 @@ void
|
||||
clutter_path_node_free (ClutterPathNode *node)
|
||||
{
|
||||
if (G_LIKELY (node))
|
||||
g_free (node);
|
||||
g_slice_free (ClutterPathNode, node);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1550,7 +1550,7 @@ clutter_knot_copy (const ClutterKnot *knot)
|
||||
if (G_UNLIKELY (knot == NULL))
|
||||
return NULL;
|
||||
|
||||
return g_memdup2 (knot, sizeof (ClutterKnot));
|
||||
return g_slice_dup (ClutterKnot, knot);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1565,7 +1565,7 @@ void
|
||||
clutter_knot_free (ClutterKnot *knot)
|
||||
{
|
||||
if (G_LIKELY (knot != NULL))
|
||||
g_free (knot);
|
||||
g_slice_free (ClutterKnot, knot);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,19 +19,7 @@
|
||||
#define CLUTTER_PICK_CONTEXT_PRIVATE_H
|
||||
|
||||
#include "clutter-pick-context.h"
|
||||
#include "clutter-pick-stack-private.h"
|
||||
|
||||
ClutterPickContext *
|
||||
clutter_pick_context_new_for_view (ClutterStageView *view,
|
||||
ClutterPickMode mode,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray);
|
||||
|
||||
ClutterPickStack *
|
||||
clutter_pick_context_steal_stack (ClutterPickContext *pick_context);
|
||||
|
||||
gboolean
|
||||
clutter_pick_context_intersects_box (ClutterPickContext *pick_context,
|
||||
const graphene_box_t *box);
|
||||
ClutterPickContext * clutter_pick_context_new_for_view (ClutterStageView *view);
|
||||
|
||||
#endif /* CLUTTER_PICK_CONTEXT_PRIVATE_H */
|
||||
|
@ -17,18 +17,13 @@
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-pick-context-private.h"
|
||||
|
||||
struct _ClutterPickContext
|
||||
{
|
||||
grefcount ref_count;
|
||||
|
||||
ClutterPickMode mode;
|
||||
ClutterPickStack *pick_stack;
|
||||
|
||||
graphene_ray_t ray;
|
||||
graphene_point3d_t point;
|
||||
CoglFramebuffer *framebuffer;
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context,
|
||||
@ -36,22 +31,14 @@ G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context,
|
||||
clutter_pick_context_unref)
|
||||
|
||||
ClutterPickContext *
|
||||
clutter_pick_context_new_for_view (ClutterStageView *view,
|
||||
ClutterPickMode mode,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray)
|
||||
clutter_pick_context_new_for_view (ClutterStageView *view)
|
||||
{
|
||||
ClutterPickContext *pick_context;
|
||||
CoglContext *context;
|
||||
|
||||
pick_context = g_new0 (ClutterPickContext, 1);
|
||||
g_ref_count_init (&pick_context->ref_count);
|
||||
pick_context->mode = mode;
|
||||
graphene_ray_init_from_ray (&pick_context->ray, ray);
|
||||
graphene_point3d_init_from_point (&pick_context->point, point);
|
||||
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
pick_context->pick_stack = clutter_pick_stack_new (context);
|
||||
pick_context->framebuffer =
|
||||
cogl_object_ref (clutter_stage_view_get_framebuffer (view));
|
||||
|
||||
return pick_context;
|
||||
}
|
||||
@ -66,7 +53,7 @@ clutter_pick_context_ref (ClutterPickContext *pick_context)
|
||||
static void
|
||||
clutter_pick_context_dispose (ClutterPickContext *pick_context)
|
||||
{
|
||||
g_clear_pointer (&pick_context->pick_stack, clutter_pick_stack_unref);
|
||||
g_clear_pointer (&pick_context->framebuffer, cogl_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
@ -87,113 +74,10 @@ clutter_pick_context_destroy (ClutterPickContext *pick_context)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_get_mode: (skip)
|
||||
* clutter_pick_context_get_framebuffer: (skip)
|
||||
*/
|
||||
ClutterPickMode
|
||||
clutter_pick_context_get_mode (ClutterPickContext *pick_context)
|
||||
CoglFramebuffer *
|
||||
clutter_pick_context_get_framebuffer (ClutterPickContext *pick_context)
|
||||
{
|
||||
return pick_context->mode;
|
||||
}
|
||||
|
||||
ClutterPickStack *
|
||||
clutter_pick_context_steal_stack (ClutterPickContext *pick_context)
|
||||
{
|
||||
clutter_pick_stack_seal (pick_context->pick_stack);
|
||||
return g_steal_pointer (&pick_context->pick_stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_log_pick:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @box: a #ClutterActorBox
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Logs a pick rectangle into the pick stack.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_log_pick (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
clutter_pick_stack_log_pick (pick_context->pick_stack, box, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_push_clip:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @box: a #ClutterActorBox
|
||||
*
|
||||
* Pushes a clip rectangle defined by @box into the pick stack. Pop with
|
||||
* clutter_pick_context_pop_clip() when done.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_push_clip (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box)
|
||||
{
|
||||
clutter_pick_stack_push_clip (pick_context->pick_stack, box);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_pop_clip:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
*
|
||||
* Pops the current clip rectangle from the clip stack. It is a programming
|
||||
* error to call this without a corresponding clutter_pick_context_push_clip()
|
||||
* call first.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_pop_clip (ClutterPickContext *pick_context)
|
||||
{
|
||||
clutter_pick_stack_pop_clip (pick_context->pick_stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_push_transform:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @transform: a #graphene_matrix_t
|
||||
*
|
||||
* Pushes @transform into the pick stack. Pop with
|
||||
* clutter_pick_context_pop_transform() when done.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_push_transform (ClutterPickContext *pick_context,
|
||||
const graphene_matrix_t *transform)
|
||||
{
|
||||
clutter_pick_stack_push_transform (pick_context->pick_stack, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_get_transform:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
* @out_matrix: (out): a #graphene_matrix_t
|
||||
*
|
||||
* Retrieves the current transform of the pick stack.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_get_transform (ClutterPickContext *pick_context,
|
||||
graphene_matrix_t *out_transform)
|
||||
{
|
||||
clutter_pick_stack_get_transform (pick_context->pick_stack, out_transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_context_pop_transform:
|
||||
* @pick_context: a #ClutterPickContext
|
||||
*
|
||||
* Pops the current transform from the clip stack. It is a programming error
|
||||
* to call this without a corresponding clutter_pick_context_push_transform()
|
||||
* call first.
|
||||
*/
|
||||
void
|
||||
clutter_pick_context_pop_transform (ClutterPickContext *pick_context)
|
||||
{
|
||||
clutter_pick_stack_pop_transform (pick_context->pick_stack);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_pick_context_intersects_box (ClutterPickContext *pick_context,
|
||||
const graphene_box_t *box)
|
||||
{
|
||||
return graphene_box_contains_point (box, &pick_context->point) ||
|
||||
graphene_ray_intersects_box (&pick_context->ray, box);
|
||||
return pick_context->framebuffer;
|
||||
}
|
||||
|
@ -44,29 +44,6 @@ CLUTTER_EXPORT
|
||||
void clutter_pick_context_destroy (ClutterPickContext *pick_context);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterPickMode clutter_pick_context_get_mode (ClutterPickContext *pick_context);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_log_pick (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_push_clip (ClutterPickContext *pick_context,
|
||||
const ClutterActorBox *box);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_pop_clip (ClutterPickContext *pick_context);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_push_transform (ClutterPickContext *pick_context,
|
||||
const graphene_matrix_t *transform);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_get_transform (ClutterPickContext *pick_context,
|
||||
graphene_matrix_t *out_matrix);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_pick_context_pop_transform (ClutterPickContext *pick_context);
|
||||
CoglFramebuffer * clutter_pick_context_get_framebuffer (ClutterPickContext *pick_context);
|
||||
|
||||
#endif /* CLUTTER_PICK_CONTEXT_H */
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Endless OS Foundation, LLC
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_PICK_STACK_PRIVATE_H
|
||||
#define CLUTTER_PICK_STACK_PRIVATE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter-macros.h"
|
||||
#include "clutter-stage-view.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_PICK_STACK (clutter_pick_stack_get_type ())
|
||||
|
||||
typedef struct _ClutterPickStack ClutterPickStack;
|
||||
|
||||
GType clutter_pick_stack_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterPickStack * clutter_pick_stack_new (CoglContext *context);
|
||||
|
||||
ClutterPickStack * clutter_pick_stack_ref (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_unref (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_seal (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_log_pick (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor);
|
||||
|
||||
void clutter_pick_stack_push_clip (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box);
|
||||
|
||||
void clutter_pick_stack_pop_clip (ClutterPickStack *pick_stack);
|
||||
|
||||
void clutter_pick_stack_push_transform (ClutterPickStack *pick_stack,
|
||||
const graphene_matrix_t *transform);
|
||||
|
||||
void clutter_pick_stack_get_transform (ClutterPickStack *pick_stack,
|
||||
graphene_matrix_t *out_transform);
|
||||
|
||||
void clutter_pick_stack_pop_transform (ClutterPickStack *pick_stack);
|
||||
|
||||
ClutterActor *
|
||||
clutter_pick_stack_search_actor (ClutterPickStack *pick_stack,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPickStack, clutter_pick_stack_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* CLUTTER_PICK_STACK_PRIVATE_H */
|
@ -1,436 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Endless OS Foundation, LLC
|
||||
* Copyright (C) 2018 Canonical Ltd.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter-pick-stack-private.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
graphene_point3d_t vertices[4];
|
||||
CoglMatrixEntry *matrix_entry;
|
||||
ClutterActorBox rect;
|
||||
gboolean projected;
|
||||
} Record;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Record base;
|
||||
ClutterActor *actor;
|
||||
int clip_index;
|
||||
} PickRecord;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Record base;
|
||||
int prev;
|
||||
} PickClipRecord;
|
||||
|
||||
struct _ClutterPickStack
|
||||
{
|
||||
grefcount ref_count;
|
||||
|
||||
CoglMatrixStack *matrix_stack;
|
||||
GArray *vertices_stack;
|
||||
GArray *clip_stack;
|
||||
int current_clip_stack_top;
|
||||
|
||||
gboolean sealed : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (ClutterPickStack, clutter_pick_stack,
|
||||
clutter_pick_stack_ref, clutter_pick_stack_unref)
|
||||
|
||||
static void
|
||||
project_vertices (CoglMatrixEntry *matrix_entry,
|
||||
const ClutterActorBox *box,
|
||||
graphene_point3d_t vertices[4])
|
||||
{
|
||||
graphene_matrix_t m;
|
||||
int i;
|
||||
|
||||
cogl_matrix_entry_get (matrix_entry, &m);
|
||||
|
||||
graphene_point3d_init (&vertices[0], box->x1, box->y1, 0.f);
|
||||
graphene_point3d_init (&vertices[1], box->x2, box->y1, 0.f);
|
||||
graphene_point3d_init (&vertices[2], box->x2, box->y2, 0.f);
|
||||
graphene_point3d_init (&vertices[3], box->x1, box->y2, 0.f);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
float w = 1.f;
|
||||
|
||||
cogl_graphene_matrix_project_point (&m,
|
||||
&vertices[i].x,
|
||||
&vertices[i].y,
|
||||
&vertices[i].z,
|
||||
&w);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_project_record (Record *rec)
|
||||
{
|
||||
if (!rec->projected)
|
||||
{
|
||||
project_vertices (rec->matrix_entry, &rec->rect, rec->vertices);
|
||||
rec->projected = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
is_axis_aligned_2d_rectangle (const graphene_point3d_t vertices[4])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (!G_APPROX_VALUE (vertices[i].z,
|
||||
vertices[(i + 1) % 4].z,
|
||||
FLT_EPSILON))
|
||||
return FALSE;
|
||||
|
||||
if (!G_APPROX_VALUE (vertices[i].x,
|
||||
vertices[(i + 1) % 4].x,
|
||||
FLT_EPSILON) &&
|
||||
!G_APPROX_VALUE (vertices[i].y,
|
||||
vertices[(i + 1) % 4].y,
|
||||
FLT_EPSILON))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ray_intersects_input_region (Record *rec,
|
||||
const graphene_ray_t *ray,
|
||||
const graphene_point3d_t *point)
|
||||
{
|
||||
maybe_project_record (rec);
|
||||
|
||||
if (G_LIKELY (is_axis_aligned_2d_rectangle (rec->vertices)))
|
||||
{
|
||||
graphene_box_t box;
|
||||
graphene_box_t right_border;
|
||||
graphene_box_t bottom_border;
|
||||
|
||||
/* Graphene considers both the start and end coordinates of boxes to be
|
||||
* inclusive, while the vertices of a clutter actor are exclusive. So we
|
||||
* need to manually exclude hits on these borders
|
||||
*/
|
||||
|
||||
graphene_box_init_from_points (&box, 4, rec->vertices);
|
||||
graphene_box_init_from_points (&right_border, 2, rec->vertices + 1);
|
||||
graphene_box_init_from_points (&bottom_border, 2, rec->vertices + 2);
|
||||
|
||||
/* Fast path for actors without 3D transforms */
|
||||
if (graphene_box_contains_point (&box, point))
|
||||
{
|
||||
return !graphene_box_contains_point (&right_border, point) &&
|
||||
!graphene_box_contains_point (&bottom_border, point);
|
||||
}
|
||||
|
||||
return graphene_ray_intersects_box (ray, &box) &&
|
||||
!graphene_ray_intersects_box (ray, &right_border) &&
|
||||
!graphene_ray_intersects_box (ray, &bottom_border);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphene_triangle_t t0, t1;
|
||||
|
||||
/*
|
||||
* Degrade the projected quad into the following triangles:
|
||||
*
|
||||
* 0 -------------- 1
|
||||
* | • |
|
||||
* | • t0 |
|
||||
* | • |
|
||||
* | t1 • |
|
||||
* | • |
|
||||
* 3 -------------- 2
|
||||
*/
|
||||
|
||||
graphene_triangle_init_from_point3d (&t0,
|
||||
&rec->vertices[0],
|
||||
&rec->vertices[1],
|
||||
&rec->vertices[2]);
|
||||
|
||||
graphene_triangle_init_from_point3d (&t1,
|
||||
&rec->vertices[0],
|
||||
&rec->vertices[2],
|
||||
&rec->vertices[3]);
|
||||
|
||||
return graphene_triangle_contains_point (&t0, point) ||
|
||||
graphene_triangle_contains_point (&t1, point) ||
|
||||
graphene_ray_intersects_triangle (ray, &t0) ||
|
||||
graphene_ray_intersects_triangle (ray, &t1);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ray_intersects_record (ClutterPickStack *pick_stack,
|
||||
PickRecord *rec,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray)
|
||||
{
|
||||
int clip_index;
|
||||
|
||||
if (!ray_intersects_input_region (&rec->base, ray, point))
|
||||
return FALSE;
|
||||
|
||||
clip_index = rec->clip_index;
|
||||
while (clip_index >= 0)
|
||||
{
|
||||
PickClipRecord *clip =
|
||||
&g_array_index (pick_stack->clip_stack, PickClipRecord, clip_index);
|
||||
|
||||
if (!ray_intersects_input_region (&clip->base, ray, point))
|
||||
return FALSE;
|
||||
|
||||
clip_index = clip->prev;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_pick_stack_weak_refs (ClutterPickStack *pick_stack)
|
||||
{
|
||||
int i;
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
|
||||
for (i = 0; i < pick_stack->vertices_stack->len; i++)
|
||||
{
|
||||
PickRecord *rec =
|
||||
&g_array_index (pick_stack->vertices_stack, PickRecord, i);
|
||||
|
||||
if (rec->actor)
|
||||
g_object_add_weak_pointer (G_OBJECT (rec->actor),
|
||||
(gpointer) &rec->actor);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_pick_stack_weak_refs (ClutterPickStack *pick_stack)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pick_stack->vertices_stack->len; i++)
|
||||
{
|
||||
PickRecord *rec =
|
||||
&g_array_index (pick_stack->vertices_stack, PickRecord, i);
|
||||
|
||||
if (rec->actor)
|
||||
g_object_remove_weak_pointer (G_OBJECT (rec->actor),
|
||||
(gpointer) &rec->actor);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_pick_stack_dispose (ClutterPickStack *pick_stack)
|
||||
{
|
||||
remove_pick_stack_weak_refs (pick_stack);
|
||||
g_clear_pointer (&pick_stack->matrix_stack, cogl_object_unref);
|
||||
g_clear_pointer (&pick_stack->vertices_stack, g_array_unref);
|
||||
g_clear_pointer (&pick_stack->clip_stack, g_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_pick_record (gpointer data)
|
||||
{
|
||||
PickRecord *rec = data;
|
||||
g_clear_pointer (&rec->base.matrix_entry, cogl_matrix_entry_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_clip_record (gpointer data)
|
||||
{
|
||||
PickClipRecord *clip = data;
|
||||
g_clear_pointer (&clip->base.matrix_entry, cogl_matrix_entry_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_stack_new:
|
||||
* @context: a #CoglContext
|
||||
*
|
||||
* Creates a new #ClutterPickStack.
|
||||
*
|
||||
* Returns: (transfer full): A newly created #ClutterPickStack
|
||||
*/
|
||||
ClutterPickStack *
|
||||
clutter_pick_stack_new (CoglContext *context)
|
||||
{
|
||||
ClutterPickStack *pick_stack;
|
||||
|
||||
pick_stack = g_new0 (ClutterPickStack, 1);
|
||||
g_ref_count_init (&pick_stack->ref_count);
|
||||
pick_stack->matrix_stack = cogl_matrix_stack_new (context);
|
||||
pick_stack->vertices_stack = g_array_new (FALSE, FALSE, sizeof (PickRecord));
|
||||
pick_stack->clip_stack = g_array_new (FALSE, FALSE, sizeof (PickClipRecord));
|
||||
pick_stack->current_clip_stack_top = -1;
|
||||
|
||||
g_array_set_clear_func (pick_stack->vertices_stack, clear_pick_record);
|
||||
g_array_set_clear_func (pick_stack->clip_stack, clear_clip_record);
|
||||
|
||||
return pick_stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_stack_ref:
|
||||
* @pick_stack: A #ClutterPickStack
|
||||
*
|
||||
* Increments the reference count of @pick_stack by one.
|
||||
*
|
||||
* Returns: (transfer full): @pick_stack
|
||||
*/
|
||||
ClutterPickStack *
|
||||
clutter_pick_stack_ref (ClutterPickStack *pick_stack)
|
||||
{
|
||||
g_ref_count_inc (&pick_stack->ref_count);
|
||||
return pick_stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_pick_stack_unref:
|
||||
* @pick_stack: A #ClutterPickStack
|
||||
*
|
||||
* Decrements the reference count of @pick_stack by one, freeing the structure
|
||||
* when the reference count reaches zero.
|
||||
*/
|
||||
void
|
||||
clutter_pick_stack_unref (ClutterPickStack *pick_stack)
|
||||
{
|
||||
if (g_ref_count_dec (&pick_stack->ref_count))
|
||||
{
|
||||
clutter_pick_stack_dispose (pick_stack);
|
||||
g_free (pick_stack);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_seal (ClutterPickStack *pick_stack)
|
||||
{
|
||||
g_assert (!pick_stack->sealed);
|
||||
add_pick_stack_weak_refs (pick_stack);
|
||||
pick_stack->sealed = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_log_pick (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
PickRecord rec;
|
||||
|
||||
g_return_if_fail (actor != NULL);
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
|
||||
rec.actor = actor;
|
||||
rec.clip_index = pick_stack->current_clip_stack_top;
|
||||
rec.base.rect = *box;
|
||||
rec.base.projected = FALSE;
|
||||
rec.base.matrix_entry = cogl_matrix_stack_get_entry (pick_stack->matrix_stack);
|
||||
cogl_matrix_entry_ref (rec.base.matrix_entry);
|
||||
|
||||
g_array_append_val (pick_stack->vertices_stack, rec);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_push_clip (ClutterPickStack *pick_stack,
|
||||
const ClutterActorBox *box)
|
||||
{
|
||||
PickClipRecord clip;
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
|
||||
clip.prev = pick_stack->current_clip_stack_top;
|
||||
clip.base.rect = *box;
|
||||
clip.base.projected = FALSE;
|
||||
clip.base.matrix_entry = cogl_matrix_stack_get_entry (pick_stack->matrix_stack);
|
||||
cogl_matrix_entry_ref (clip.base.matrix_entry);
|
||||
|
||||
g_array_append_val (pick_stack->clip_stack, clip);
|
||||
pick_stack->current_clip_stack_top = pick_stack->clip_stack->len - 1;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_pop_clip (ClutterPickStack *pick_stack)
|
||||
{
|
||||
const PickClipRecord *top;
|
||||
|
||||
g_assert (!pick_stack->sealed);
|
||||
g_assert (pick_stack->current_clip_stack_top >= 0);
|
||||
|
||||
/* Individual elements of clip_stack are not freed. This is so they can
|
||||
* be shared as part of a tree of different stacks used by different
|
||||
* actors in the pick_stack. The whole clip_stack does however get
|
||||
* freed later in clutter_pick_stack_dispose.
|
||||
*/
|
||||
|
||||
top = &g_array_index (pick_stack->clip_stack,
|
||||
PickClipRecord,
|
||||
pick_stack->current_clip_stack_top);
|
||||
|
||||
pick_stack->current_clip_stack_top = top->prev;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_push_transform (ClutterPickStack *pick_stack,
|
||||
const graphene_matrix_t *transform)
|
||||
{
|
||||
cogl_matrix_stack_push (pick_stack->matrix_stack);
|
||||
cogl_matrix_stack_multiply (pick_stack->matrix_stack, transform);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_get_transform (ClutterPickStack *pick_stack,
|
||||
graphene_matrix_t *out_transform)
|
||||
{
|
||||
cogl_matrix_stack_get (pick_stack->matrix_stack, out_transform);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_pick_stack_pop_transform (ClutterPickStack *pick_stack)
|
||||
{
|
||||
cogl_matrix_stack_pop (pick_stack->matrix_stack);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
clutter_pick_stack_search_actor (ClutterPickStack *pick_stack,
|
||||
const graphene_point3d_t *point,
|
||||
const graphene_ray_t *ray)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Search all "painted" pickable actors from front to back. A linear search
|
||||
* is required, and also performs fine since there is typically only
|
||||
* on the order of dozens of actors in the list (on screen) at a time.
|
||||
*/
|
||||
for (i = pick_stack->vertices_stack->len - 1; i >= 0; i--)
|
||||
{
|
||||
PickRecord *rec =
|
||||
&g_array_index (pick_stack->vertices_stack, PickRecord, i);
|
||||
|
||||
if (rec->actor && ray_intersects_record (pick_stack, rec, point, ray))
|
||||
return rec->actor;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
@ -44,6 +44,7 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _ClutterMainContext ClutterMainContext;
|
||||
typedef struct _ClutterVertex4 ClutterVertex4;
|
||||
|
||||
#define CLUTTER_REGISTER_VALUE_TRANSFORM_TO(TYPE_TO,func) { \
|
||||
g_value_register_transform_func (g_define_type_id, TYPE_TO, func); \
|
||||
@ -121,12 +122,14 @@ struct _ClutterMainContext
|
||||
ClutterStageManager *stage_manager;
|
||||
|
||||
/* the main event queue */
|
||||
GAsyncQueue *events_queue;
|
||||
GQueue *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;
|
||||
|
||||
ClutterPickMode pick_mode;
|
||||
|
||||
/* default FPS; this is only used if we cannot sync to vblank */
|
||||
guint frame_rate;
|
||||
|
||||
@ -173,8 +176,8 @@ void _clutter_threads_dispatch_free (gpointer data);
|
||||
ClutterMainContext * _clutter_context_get_default (void);
|
||||
void _clutter_context_lock (void);
|
||||
void _clutter_context_unlock (void);
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_context_is_initialized (void);
|
||||
ClutterPickMode _clutter_context_get_pick_mode (void);
|
||||
gboolean _clutter_context_get_show_fps (void);
|
||||
|
||||
gboolean _clutter_feature_init (GError **error);
|
||||
@ -208,18 +211,16 @@ void _clutter_run_repaint_functions (ClutterRepaintFlags flags);
|
||||
|
||||
GType _clutter_layout_manager_get_child_meta_type (ClutterLayoutManager *manager);
|
||||
|
||||
void _clutter_util_fully_transform_vertices (const graphene_matrix_t *modelview,
|
||||
const graphene_matrix_t *projection,
|
||||
void _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
|
||||
const CoglMatrix *projection,
|
||||
const float *viewport,
|
||||
const graphene_point3d_t *vertices_in,
|
||||
graphene_point3d_t *vertices_out,
|
||||
int n_vertices);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_util_rect_from_rectangle (const cairo_rectangle_int_t *src,
|
||||
graphene_rect_t *dest);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_util_rectangle_int_extents (const graphene_rect_t *src,
|
||||
cairo_rectangle_int_t *dest);
|
||||
|
||||
@ -239,17 +240,62 @@ gboolean _clutter_util_rectangle_intersection (const cairo_rectangle_int_t *src1
|
||||
gboolean clutter_util_rectangle_equal (const cairo_rectangle_int_t *src1,
|
||||
const cairo_rectangle_int_t *src2);
|
||||
|
||||
|
||||
struct _ClutterVertex4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
};
|
||||
|
||||
void
|
||||
_clutter_util_vertex4_interpolate (const ClutterVertex4 *a,
|
||||
const ClutterVertex4 *b,
|
||||
double progress,
|
||||
ClutterVertex4 *res);
|
||||
|
||||
#define CLUTTER_MATRIX_INIT_IDENTITY { \
|
||||
1.0f, 0.0f, 0.0f, 0.0f, \
|
||||
0.0f, 1.0f, 0.0f, 0.0f, \
|
||||
0.0f, 0.0f, 1.0f, 0.0f, \
|
||||
0.0f, 0.0f, 0.0f, 1.0f, \
|
||||
}
|
||||
|
||||
float _clutter_util_matrix_determinant (const ClutterMatrix *matrix);
|
||||
|
||||
void _clutter_util_matrix_skew_xy (ClutterMatrix *matrix,
|
||||
float factor);
|
||||
void _clutter_util_matrix_skew_xz (ClutterMatrix *matrix,
|
||||
float factor);
|
||||
void _clutter_util_matrix_skew_yz (ClutterMatrix *matrix,
|
||||
float factor);
|
||||
|
||||
gboolean _clutter_util_matrix_decompose (const ClutterMatrix *src,
|
||||
graphene_point3d_t *scale_p,
|
||||
float shear_p[3],
|
||||
graphene_point3d_t *rotate_p,
|
||||
graphene_point3d_t *translate_p,
|
||||
ClutterVertex4 *perspective_p);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
PangoDirection _clutter_pango_unichar_direction (gunichar ch);
|
||||
|
||||
PangoDirection _clutter_pango_find_base_dir (const gchar *text,
|
||||
gint length);
|
||||
|
||||
typedef struct _ClutterPlane
|
||||
{
|
||||
graphene_vec3_t v0;
|
||||
graphene_vec3_t n;
|
||||
} ClutterPlane;
|
||||
|
||||
typedef enum _ClutterCullResult
|
||||
{
|
||||
CLUTTER_CULL_RESULT_UNKNOWN,
|
||||
CLUTTER_CULL_RESULT_IN,
|
||||
CLUTTER_CULL_RESULT_OUT,
|
||||
CLUTTER_CULL_RESULT_PARTIAL
|
||||
} ClutterCullResult;
|
||||
|
||||
gboolean _clutter_has_progress_function (GType gtype);
|
||||
@ -261,78 +307,30 @@ gboolean _clutter_run_progress_function (GType gtype,
|
||||
|
||||
void clutter_timeline_cancel_delay (ClutterTimeline *timeline);
|
||||
|
||||
static inline void
|
||||
clutter_round_to_256ths (float *f)
|
||||
{
|
||||
*f = roundf ((*f) * 256) / 256;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ns (uint64_t ns)
|
||||
{
|
||||
return ns;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us (int64_t us)
|
||||
us (uint64_t us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
ms (int64_t ms)
|
||||
{
|
||||
return ms;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
ms2us (int64_t ms)
|
||||
static inline uint64_t
|
||||
ms2us (uint64_t ms)
|
||||
{
|
||||
return us (ms * 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us2ns (int64_t us)
|
||||
static inline uint32_t
|
||||
us2ms (uint64_t us)
|
||||
{
|
||||
return ns (us * 1000);
|
||||
return (uint32_t) (us / 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us2ms (int64_t us)
|
||||
{
|
||||
return (int64_t) (us / 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
ns2us (int64_t ns)
|
||||
static inline uint64_t
|
||||
ns2us (uint64_t ns)
|
||||
{
|
||||
return us (ns / 1000);
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
s2us (int64_t s)
|
||||
{
|
||||
return s * G_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
us2s (int64_t us)
|
||||
{
|
||||
return us / G_USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
s2ns (int64_t s)
|
||||
{
|
||||
return us2ns (s2us (s));
|
||||
}
|
||||
|
||||
static inline int64_t
|
||||
s2ms (int64_t s)
|
||||
{
|
||||
return (int64_t) ms (s * 1000);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PRIVATE_H__ */
|
||||
|
@ -161,7 +161,7 @@ _clutter_script_get_type_from_class (const gchar *name)
|
||||
* The enumeration value can be an integer, the enumeration nick
|
||||
* or the enumeration name, as part of the #GEnumValue structure.
|
||||
*
|
||||
* Return value: %TRUE if the conversion was successful.
|
||||
* Return value: %TRUE if the conversion was successfull.
|
||||
*/
|
||||
gboolean
|
||||
_clutter_script_enum_from_string (GType type,
|
||||
@ -733,7 +733,7 @@ parse_signals (ClutterScript *script,
|
||||
state != NULL ? state : "<default>", target,
|
||||
warp_to ? "true" : "false");
|
||||
|
||||
sinfo = g_new0 (SignalInfo, 1);
|
||||
sinfo = g_slice_new0 (SignalInfo);
|
||||
sinfo->is_handler = FALSE;
|
||||
sinfo->name = g_strdup (name);
|
||||
sinfo->state = g_strdup (state);
|
||||
@ -780,7 +780,7 @@ parse_signals (ClutterScript *script,
|
||||
name,
|
||||
handler, connect, flags);
|
||||
|
||||
sinfo = g_new0 (SignalInfo, 1);
|
||||
sinfo = g_slice_new0 (SignalInfo);
|
||||
sinfo->is_handler = TRUE;
|
||||
sinfo->name = g_strdup (name);
|
||||
sinfo->handler = g_strdup (handler);
|
||||
@ -852,7 +852,7 @@ clutter_script_parser_object_end (JsonParser *json_parser,
|
||||
{
|
||||
const gchar *class_name;
|
||||
|
||||
oinfo = g_new0 (ObjectInfo, 1);
|
||||
oinfo = g_slice_new0 (ObjectInfo);
|
||||
oinfo->merge_id = _clutter_script_get_last_merge_id (script);
|
||||
oinfo->id = g_strdup (id_);
|
||||
oinfo->has_unresolved = TRUE;
|
||||
@ -938,7 +938,7 @@ clutter_script_parser_object_end (JsonParser *json_parser,
|
||||
continue;
|
||||
}
|
||||
|
||||
pinfo = g_new0 (PropertyInfo, 1);
|
||||
pinfo = g_slice_new (PropertyInfo);
|
||||
|
||||
pinfo->name = g_strdup (name);
|
||||
pinfo->node = json_node_copy (node);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user