Compare commits

..

12 Commits

Author SHA1 Message Date
Ray Strode
7f4f9b122e wip! native: release dumb fb after flip for EGLStreams
fixme probably need to recreate the dumb fb any time doing
an explicit modeset
2018-11-30 14:34:10 -05:00
Ray Strode
82f03c51ac wip! renderer/native: start to add stream copy mode
At the moment, mutter only supports using GBM for
doing GPU blits to secondary video cards.

This commit starts to sketch out using eglstreams
for doing the copy.

FIXME: in order to get memcpy fastpath we get
inverted colors and have to fix it up in the shader.

FIXME: need to move some of the globals to be in
a more structured place

Closes https://gitlab.gnome.org/GNOME/mutter/issues/205
2018-11-30 14:34:10 -05:00
Ray Strode
8f538671d6 wip! renderer/native: only flip secondary crtc if using GBM
It's possible that the secondary gpu isn't using GBM for
renderering. if that's the case we shouldn't try to flip using
drm apis.

This commit checks, and only does the flip when expected.
2018-11-30 14:34:10 -05:00
Ray Strode
0540e4dc45 wip! renderer/native: generalize flip_egl_stream
We're going to need to be able to flip secondary egl streams,
so this commit parameterizes the stream and related objects.

A new wrapper function, `flip_primary_egl_stream`, takes over the
previous role of `flip_egl_stream`

fixme no_egl_output_drm_flip_event needs to be handled for secondary
streams
2018-11-30 14:34:10 -05:00
Ray Strode
5d8248d65b renderer/native: initialize egldevice on secondary cards
If possible initialize the egldevice renderer on secondary
cards.
2018-11-30 14:34:10 -05:00
Ray Strode
b61c2f2120 wip! renderer/native: separate renderer gpu data initialization from creation
We're going to need to initialize both gbm and egldevice based rendering
on some machines for one renderer data, so this commit splits
initialization out from construction.
2018-11-30 14:34:10 -05:00
Ray Strode
3dacd0f6f5 wip! renderer/native: generalize meta_renderer_native_create_surface_egl_device
Eventually we want to use meta_renderer_native_create_surface_egl_device
for secondary displays, but it currently implicitly uses the primary
display and egl context.

This commit changes the function to take a display and a context
as arguments.
2018-11-30 14:34:10 -05:00
Ray Strode
336cb36d3c wip! renderer/native: pass MetaMonitor instead of MetaLogicalMonitor to meta_renderer_native_create_surface_egl_device 2018-11-30 14:34:10 -05:00
Ray Strode
bb33dad473 wip! renderer-native: use proper surface type for egldevice 2018-11-30 14:34:09 -05:00
Ray Strode
88a7b6e1da renderer/native: use GBM_FORMAT_ARGB8888 for primary rendering format
At the moment we use GBM_FORMAT_XRGB8888 which unfortunately triggers
slow read pixels code in mesa.

This commit changes it to ARGB8888 instead, which copies with memcpy.
2018-11-30 14:34:09 -05:00
Pekka Paalanen
008a12a637 cogl: pick glReadPixels format by target, not source
Presumably glReadPixels itself can be more performant with pixel format
conversions than doing a fix-up conversion on the CPU afterwards. Hence,
pick required_format based on the destination rather than the source, so
that it has a better chance to avoid the fix-up conversion.

With CoglOnscreen objects, CoglFramebuffer::internal_format (the source
format) is also wrong. It is left to a default value and never set to
reflect the reality. In other words, read-pixels had an arbitrary
intermediate pixel format that was used in glReadPixels and then fix-up
conversion made it work for the destination.

The render buffers (GBM surface) are allocated as DRM_FORMAT_XRGB8888.
If the destination buffer is allocated as the same format, the Cogl
read-pixels first converts with glReadPixels XRGB -> ABGR because of the
above default format, and then the fix-up conversion does ABGR -> XRGB.
This case was observed with DisplayLink outputs, where the native
renderer must use the CPU copy path to fill the "secondary GPU"
framebuffers.

This patch stops using internal_format and uses the desired destination
format instead.

_cogl_framebuffer_gl_read_pixels_into_bitmap() will still use
internal_format to determine alpha premultiplication state and multiply
or un-multiply as needed. Luckily all the formats involved in the
DisplayLink use case are always _PRE and so is the default
internal_format too, so things work in practise.

Furthermore, the GL texture_swizzle extension can never apply to
glReadPixels. Not even with FBOs, as found in this discussion:
https://gitlab.gnome.org/GNOME/mutter/issues/72
Therefore the target_format argument is hardcoded to something that can
never match anything, which will prevent the swizzle from being assumed.
2018-11-30 14:34:09 -05:00
Pekka Paalanen
c8112a1dbc cogl: remove mesa_46631_slow_read_pixels_workaround
This function gets hit even today on relatively modern Intel systems (I
have a Haswell Desktop with Mesa 18.2.4) if the pixel format is right.
Presumably it makes things slower for no longer a reason.

According to cb146dc515bf484192a8edfab716550a996b05df, this
functionality was refactored into a workaround path in 2012. The commit
message mentions the problem existing before Mesa 8.0.2. The number
refers to https://bugs.freedesktop.org/show_bug.cgi?id=46631 .

The use case where I hit this is when improving support for DisplayLink
video outputs. These are used through a "secondary GPU", and since
DisplayLink does not have a GPU, Mutter uses the CPU copy path with Cogl
read-pixels[1]. If the DisplayLink framebuffer was allocated as
DRM_FORMAT_XRGB8888 (the only format it currently handles correctly),
mesa_46631_slow_read_pixels_workaround would get hit. The render buffer is
the same format as the framebuffer, yet doing the copy XRGB -> XRGB ends
up being slower than XRGB -> XBGR which makes no sense.

This patch is not sufficient to fix the XRGB -> XRGB copy performance,
but it is required.

This patch reverts CoglGpuInfoDriverBug into what it was before
cb146dc515bf484192a8edfab716550a996b05df.

[1] This is not actually true until
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/278 is
    merged.
2018-11-30 14:34:09 -05:00
1711 changed files with 208864 additions and 168319 deletions

30
.gitignore vendored
View File

@ -1,9 +1,25 @@
Makefile
Makefile.in
Makefile.in.in
aclocal.m4
autom4te.cache
build-aux
compile
config.guess
config.h
config.h.in
config.log
config.status
config.sub
configure
depcomp
install-sh
intltool-extract.in
intltool-merge.in
libtool
ltmain.sh
missing
.deps
50-mutter-navigation.xml
50-mutter-system.xml
50-mutter-windows.xml
@ -17,11 +33,15 @@ mutter-wayland.desktop
*.swp
*.gir
*.typelib
stamp-h1
*.gmo
*.make
*.log
*.trs
*~
stamp-it
.intltool-merge-cache
ABOUT-NLS
POTFILES
Makevars.template
po/*.header
@ -44,7 +64,9 @@ org.gnome.mutter.wayland.gschema.xml
testasyncgetprop
testboxes
testgradient
m4/*
INSTALL
mkinstalldirs
meta-enum-types.[ch]
src/stamp-meta-enum-types.h
src/meta-dbus-display-config.[ch]
@ -100,7 +122,13 @@ doc/reference/meta-undocumented.txt
doc/reference/meta-unused.txt
doc/reference/meta-docs.sgml
doc/reference/meta.types
gtk-doc.m4
intltool.m4
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
.dirstamp
**/tags.*
build/
subprojects/sysprof/

View File

@ -1,372 +1,20 @@
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:v1
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'
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
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
artifacts:
expire_in: 1 day
paths:
- build
- meson . build -Degl_device=true -Dwayland_eglstream=true
- ninja -C build
- ninja -C build install
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
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
artifacts:
paths:
- build/meson-logs
build-without-native-backend-and-wayland@x86_64:
extends:
- .fdo.distribution-image@fedora
- .mutter.fedora:34@x86_64
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
artifacts:
paths:
- build/meson-logs
.test-setup: &test-setup
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
MUTTER_DEBUG_DUMMY_MODE_SPECS: "800x600@10.0"
PIPEWIRE_DEBUG: 2
PIPEWIRE_LOG: "$CI_PROJECT_DIR/build/meson-logs/pipewire.log"
XVFB_SERVER_ARGS: "+iglx -noreset"
G_SLICE: "always-malloc"
MALLOC_CHECK_: "3"
NO_AT_BRIDGE: "1"
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
test-mutter:
stage: test
script:
- dbus-run-session -- xvfb-run -a -s "$XVFB_SERVER_ARGS"
catchsegv meson test -C build --no-rebuild -t 10
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
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
script:
- ninja -C build coverage
- cat build/meson-logs/coverage.txt
artifacts:
paths:
- build/meson-logs/coveragereport
coverage: '/^TOTAL.*\s+(\d+\%)$/'
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
stage: test
needs:
- build-mutter@x86_64
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'
- meson . build -Degl_device=true -Dwayland_eglstream=true
- ninja -C build
- glib-compile-schemas $PWD/build/data
- env XDG_RUNTIME_DIR=/tmp/ GSETTINGS_SCHEMA_DIR=$PWD/build/data dbus-run-session -- xvfb-run -s '+iglx -noreset' meson test -C build -t 10 --verbose --no-stdsplit --wrap catchsegv

14
.gitlab-ci/Dockerfile Normal file
View File

@ -0,0 +1,14 @@
FROM fedora:29
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(builddep)' && \
dnf builddep -y mutter && \
# Until Fedora catches up with meson build-deps
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland && \
# For running unit tests
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 && \
dnf install -y intltool redhat-rpm-config make && \
dnf clean all

View File

@ -1,55 +0,0 @@
#!/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
exit 1
fi
cd gnome-shell
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
merge_request_remote=${CI_MERGE_REQUEST_SOURCE_PROJECT_URL//mutter/gnome-shell}
merge_request_branch=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
echo -n Looking for $merge_request_branch on remote ...
if fetch $merge_request_remote $merge_request_branch; then
echo \ found
gnome_shell_target=FETCH_HEAD
else
echo \ not found
echo -n Looking for $CI_MERGE_REQUEST_TARGET_BRANCH_NAME instead ...
if fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME; then
echo \ found
gnome_shell_target=FETCH_HEAD
else
echo \ not found
fi
fi
fi
if [ -z "$gnome_shell_target" ]; then
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
echo Using $gnome_shell_target instead
fi
fi
git checkout -q $gnome_shell_target

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -1,55 +0,0 @@
<!--
Please read https://wiki.gnome.org/Community/GettingInTouch/BugReportingGuidelines
first to ensure that you create a clear and specific issue.
-->
### Affected version
<!--
Provide at least the following information:
* Your OS and version
* Affected Mutter version
* Does this issue appear in XOrg and/or Wayland
-->
### Bug summary
<!--
Provide a short summary of the bug you encountered.
-->
### Steps to reproduce
<!--
1. Step one
2. Step two
3. ...
-->
### What happened
<!--
What did Mutter do that was unexpected?
-->
### What did you expect to happen
<!--
What did you expect Mutter to do?
-->
### Relevant logs, screenshots, screencasts etc.
<!--
If you have further information, such as technical documentation, logs,
screenshots or screencasts related, please provide them here.
If the bug is a crash, please obtain a stack trace with installed debug
symbols (at least for GNOME Shell and Mutter) and attach it to
this issue following the instructions on
https://wiki.gnome.org/Community/GettingInTouch/Bugzilla/GettingTraces.
-->
<!-- Do not remove the following line. -->
/label ~"1. Bug"

View File

@ -1,30 +0,0 @@
<!--
Please read https://wiki.gnome.org/Community/GettingInTouch/BugReportingGuidelines
first to ensure that you create a clear and specific issue.
-->
### Feature summary
<!--
Describe what you would like to be able to do with Mutter
that you currently cannot do.
-->
### How would you like it to work
<!--
If you can think of a way Mutter might be able to do this,
let us know here.
-->
### Relevant links, screenshots, screencasts etc.
<!--
If you have further information, such as technical documentation,
code, mockups or a similar feature in another window managers,
please provide them here.
-->
<!-- Do not remove the following line. -->
/label ~"1. Feature"

View File

@ -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

13
Makefile.am Normal file
View File

@ -0,0 +1,13 @@
pkgdatadir = $(datadir)/mutter-$(LIBMUTTER_API_VERSION)
pkglibdir = $(libdir)/mutter-$(LIBMUTTER_API_VERSION)
SUBDIRS = cogl clutter data src po doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
DISTCLEANFILES = \
intltool-extract \
intltool-merge \
intltool-update \
po/stamp-it \
po/.intltool-merge-cache

1118
NEWS

File diff suppressed because it is too large Load Diff

View File

@ -22,39 +22,6 @@ by Gala, elementary OS's window manager. It can also be run standalone, using
the command "mutter", but just running plain mutter is only intended for
debugging purposes.
## Contributing
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter.
It can be useful to 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
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
```
## License
Mutter is distributed under the terms of the GNU General Public License,

28
autogen.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
# Run this to generate all the initial makefiles, etc.
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
REQUIRED_AUTOMAKE_VERSION=1.11
olddir="$(pwd)"
cd "${srcdir}"
(test -f configure.ac \
&& test -d src) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level mutter directory"
exit 1
}
aclocal --install || exit 1
intltoolize --force --copy --automake || exit 1
autoreconf --verbose --force --install || exit 1
cd "${olddir}"
if [ "$NOCONFIGURE" = "" ]; then
"${srcdir}/configure" "$@" || exit 1
fi

View File

@ -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)

49
clutter/Makefile.am Normal file
View File

@ -0,0 +1,49 @@
NULL =
SUBDIRS = build clutter tests
DIST_SUBDIRS = clutter tests build
# XXX - this is a massive hack to make autoreconf honour the ACLOCAL_FLAGS
# that jhbuild sets while still retaining build/autotools as the authoritative
# source for m4 macros
ACLOCAL_AMFLAGS = -I build/autotools ${ACLOCAL_FLAGS}
CLEANFILES = $(pcfiles)
DISTCLEANFILES =
DISTCHECK_CONFIGURE_FLAGS = --enable-maintainer-flags
# proxy rules for tests
test-report full-report:
$(MAKE) -C tests/conform $(@)
perf-report:
$(MAKE) -C tests/performance $(@)
if ENABLE_GCOV
# use recursive makes in order to ignore errors during check/perf
lcov:
-$(MAKE) $(AM_MAKEFLAGS) -C clutter check
-$(MAKE) $(AM_MAKEFLAGS) -C tests/conform test
$(MAKE) $(AM_MAKEFLAGS) genlcov
# we have to massage the lcov.info file slightly to hide the effect of libtool
# placing the objects files in the .libs/ directory separate from the *.c
genlcov:
$(LTP) --directory $(top_builddir) --capture --output-file clutter-lcov.info --test-name CLUTTER_TEST --no-checksum
$(SED) -e 's#.libs/##' < clutter-lcov.info > clutter-lcov.info.tmp
LANG=C $(LTP_GENHTML) --prefix $(top_builddir) --output-directory clutter-lcov --title "Clutter Code Coverage" --show-details clutter-lcov.info.tmp
rm -f clutter-lcov.info.tmp
lcov-clean:
-$(LTP) --directory $(top_builddir) -z
-$(RM) -rf clutter-lcov.info clutter-lcov
else
lcov genlcov lcov-clean:
@echo You need to configure Clutter with support for gcov enabled.
@echo e.g., ./configure --enable-gcov
endif
.PHONY: test-report full-report perf-report lcov genlcov lcov-clean

View File

@ -0,0 +1 @@
SUBDIRS = autotools

8
clutter/build/autotools/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
gtk-doc.m4
libtool.m4
ltoptions.m4
ltsugar.m4
ltversion.m4
lt~obsolete.m4
shave
shave-libtool

View File

@ -0,0 +1,10 @@
NULL =
EXTRA_DIST = \
introspection.m4 \
as-compiler-flag.m4 \
glibtests.m4 \
glib-tap.mk \
tap-driver.sh \
tap-test \
$(NULL)

View File

@ -0,0 +1,62 @@
dnl as-compiler-flag.m4 0.1.0
dnl autostars m4 macro for detection of compiler flags
dnl David Schleef <ds@schleef.org>
dnl $Id: as-compiler-flag.m4,v 1.1 2005/12/15 23:35:19 ds Exp $
dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
dnl Tries to compile with the given CFLAGS.
dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
dnl and ACTION-IF-NOT-ACCEPTED otherwise.
AC_DEFUN([AS_COMPILER_FLAG],
[
AC_MSG_CHECKING([to see if compiler understands $1])
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
CFLAGS="$save_CFLAGS"
if test "X$flag_ok" = Xyes ; then
m4_ifvaln([$2],[$2])
true
else
m4_ifvaln([$3],[$3])
true
fi
AC_MSG_RESULT([$flag_ok])
])
dnl AS_COMPILER_FLAGS(VAR, FLAGS)
dnl Tries to compile with the given CFLAGS.
AC_DEFUN([AS_COMPILER_FLAGS],
[
list=$2
flags_supported=""
flags_unsupported=""
AC_MSG_CHECKING([for supported compiler flags])
for each in $list
do
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $each"
AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
CFLAGS="$save_CFLAGS"
if test "X$flag_ok" = Xyes ; then
flags_supported="$flags_supported $each"
else
flags_unsupported="$flags_unsupported $each"
fi
done
AC_MSG_RESULT([$flags_supported])
if test "X$flags_unsupported" != X ; then
AC_MSG_WARN([unsupported compiler flags: $flags_unsupported])
fi
$1="$$1 $flags_supported"
])

View File

@ -0,0 +1,134 @@
# GLIB - Library of useful C routines
TESTS_ENVIRONMENT= \
G_TEST_SRCDIR="$(abs_srcdir)" \
G_TEST_BUILDDIR="$(abs_builddir)" \
G_DEBUG=gc-friendly \
MALLOC_CHECK_=2 \
MALLOC_PERTURB_=$$(($${RANDOM:-256} % 256))
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/build/autotools/tap-driver.sh
LOG_COMPILER = $(top_srcdir)/build/autotools/tap-test
NULL =
# initialize variables for unconditional += appending
BUILT_SOURCES =
BUILT_EXTRA_DIST =
CLEANFILES = *.log *.trs
DISTCLEANFILES =
MAINTAINERCLEANFILES =
EXTRA_DIST =
TESTS =
installed_test_LTLIBRARIES =
installed_test_PROGRAMS =
installed_test_SCRIPTS =
nobase_installed_test_DATA =
noinst_LTLIBRARIES =
noinst_PROGRAMS =
noinst_SCRIPTS =
noinst_DATA =
check_LTLIBRARIES =
check_PROGRAMS =
check_SCRIPTS =
check_DATA =
# We support a fairly large range of possible variables. It is expected that all types of files in a test suite
# will belong in exactly one of the following variables.
#
# First, we support the usual automake suffixes, but in lowercase, with the customary meaning:
#
# test_programs, test_scripts, test_data, test_ltlibraries
#
# The above are used to list files that are involved in both uninstalled and installed testing. The
# test_programs and test_scripts are taken to be actual testcases and will be run as part of the test suite.
# Note that _data is always used with the nobase_ automake variable name to ensure that installed test data is
# installed in the same way as it appears in the package layout.
#
# In order to mark a particular file as being only for one type of testing, use 'installed' or 'uninstalled',
# like so:
#
# installed_test_programs, uninstalled_test_programs
# installed_test_scripts, uninstalled_test_scripts
# installed_test_data, uninstalled_test_data
# installed_test_ltlibraries, uninstalled_test_ltlibraries
#
# Additionally, we support 'extra' infixes for programs and scripts. This is used for support programs/scripts
# that should not themselves be run as testcases (but exist to be used from other testcases):
#
# test_extra_programs, installed_test_extra_programs, uninstalled_test_extra_programs
# test_extra_scripts, installed_test_extra_scripts, uninstalled_test_extra_scripts
#
# Additionally, for _scripts and _data, we support the customary dist_ prefix so that the named script or data
# file automatically end up in the tarball.
#
# dist_test_scripts, dist_test_data, dist_test_extra_scripts
# dist_installed_test_scripts, dist_installed_test_data, dist_installed_test_extra_scripts
# dist_uninstalled_test_scripts, dist_uninstalled_test_data, dist_uninstalled_test_extra_scripts
#
# Note that no file is automatically disted unless it appears in one of the dist_ variables. This follows the
# standard automake convention of not disting programs scripts or data by default.
#
# test_programs, test_scripts, uninstalled_test_programs and uninstalled_test_scripts (as well as their disted
# variants) will be run as part of the in-tree 'make check'. These are all assumed to be runnable under
# gtester. That's a bit strange for scripts, but it's possible.
TESTS += $(test_programs) $(test_scripts) $(uninstalled_test_programs) $(uninstalled_test_scripts) \
$(dist_test_scripts) $(dist_uninstalled_test_scripts)
# Note: build even the installed-only targets during 'make check' to ensure that they still work.
# We need to do a bit of trickery here and manage disting via EXTRA_DIST instead of using dist_ prefixes to
# prevent automake from mistreating gmake functions like $(wildcard ...) and $(addprefix ...) as if they were
# filenames, including removing duplicate instances of the opening part before the space, eg. '$(addprefix'.
all_test_programs = $(test_programs) $(uninstalled_test_programs) $(installed_test_programs) \
$(test_extra_programs) $(uninstalled_test_extra_programs) $(installed_test_extra_programs)
all_test_scripts = $(test_scripts) $(uninstalled_test_scripts) $(installed_test_scripts) \
$(test_extra_scripts) $(uninstalled_test_extra_scripts) $(installed_test_extra_scripts)
all_dist_test_scripts = $(dist_test_scripts) $(dist_uninstalled_test_scripts) $(dist_installed_test_scripts) \
$(dist_test_extra_scripts) $(dist_uninstalled_test_extra_scripts) $(dist_installed_test_extra_scripts)
all_test_scripts += $(all_dist_test_scripts)
EXTRA_DIST += $(all_dist_test_scripts)
all_test_data = $(test_data) $(uninstalled_test_data) $(installed_test_data)
all_dist_test_data = $(dist_test_data) $(dist_uninstalled_test_data) $(dist_installed_test_data)
all_test_data += $(all_dist_test_data)
EXTRA_DIST += $(all_dist_test_data)
all_test_ltlibs = $(test_ltlibraries) $(uninstalled_test_ltlibraries) $(installed_test_ltlibraries)
if ENABLE_ALWAYS_BUILD_TESTS
noinst_LTLIBRARIES += $(all_test_ltlibs)
noinst_PROGRAMS += $(all_test_programs)
noinst_SCRIPTS += $(all_test_scripts)
noinst_DATA += $(all_test_data)
else
check_LTLIBRARIES += $(all_test_ltlibs)
check_PROGRAMS += $(all_test_programs)
check_SCRIPTS += $(all_test_scripts)
check_DATA += $(all_test_data)
endif
if ENABLE_INSTALLED_TESTS
installed_test_PROGRAMS += $(test_programs) $(installed_test_programs) \
$(test_extra_programs) $(installed_test_extra_programs)
installed_test_SCRIPTS += $(test_scripts) $(installed_test_scripts) \
$(test_extra_scripts) $(test_installed_extra_scripts)
installed_test_SCRIPTS += $(dist_test_scripts) $(dist_test_extra_scripts) \
$(dist_installed_test_scripts) $(dist_installed_test_extra_scripts)
nobase_installed_test_DATA += $(test_data) $(installed_test_data)
nobase_installed_test_DATA += $(dist_test_data) $(dist_installed_test_data)
installed_test_LTLIBRARIES += $(test_ltlibraries) $(installed_test_ltlibraries)
installed_testcases = $(test_programs) $(installed_test_programs) \
$(test_scripts) $(installed_test_scripts) \
$(dist_test_scripts) $(dist_installed_test_scripts)
installed_test_meta_DATA = $(installed_testcases:=.test)
%.test: %$(EXEEXT) Makefile
$(AM_V_GEN) (echo '[Test]' > $@.tmp; \
echo 'Type=session' >> $@.tmp; \
echo 'Exec=env G_ENABLE_DIAGNOSTIC=0 CLUTTER_ENABLE_DIAGNOSTIC=0 $(installed_testdir)/$<' >> $@.tmp; \
mv $@.tmp $@)
CLEANFILES += $(installed_test_meta_DATA)
endif

View File

@ -0,0 +1,28 @@
dnl GLIB_TESTS
dnl
AC_DEFUN([GLIB_TESTS],
[
AC_ARG_ENABLE(installed-tests,
AS_HELP_STRING([--enable-installed-tests],
[Enable installation of some test cases]),
[case ${enableval} in
yes) ENABLE_INSTALLED_TESTS="1" ;;
no) ENABLE_INSTALLED_TESTS="" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;;
esac])
AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1")
AC_ARG_ENABLE(always-build-tests,
AS_HELP_STRING([--enable-always-build-tests],
[Enable always building tests during 'make all']),
[case ${enableval} in
yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;;
no) ENABLE_ALWAYS_BUILD_TESTS="" ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;;
esac])
AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1")
if test "$ENABLE_INSTALLED_TESTS" = "1"; then
AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME)
AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME)
fi
])

View File

@ -0,0 +1,96 @@
dnl -*- mode: autoconf -*-
dnl Copyright 2009 Johan Dahlin
dnl
dnl This file is free software; the author(s) gives unlimited
dnl permission to copy and/or distribute it, with or without
dnl modifications, as long as this notice is preserved.
dnl
# serial 1
m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
[
AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
dnl enable/disable introspection
m4_if([$2], [require],
[dnl
enable_introspection=yes
],[dnl
AC_ARG_ENABLE(introspection,
AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
[Enable introspection for this build]),,
[enable_introspection=auto])
])dnl
AC_MSG_CHECKING([for gobject-introspection])
dnl presence/version checking
AS_CASE([$enable_introspection],
[no], [dnl
found_introspection="no (disabled, use --enable-introspection to enable)"
],dnl
[yes],[dnl
PKG_CHECK_EXISTS([gobject-introspection-1.0],,
AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
found_introspection=yes,
AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
],dnl
[auto],[dnl
PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
dnl Canonicalize enable_introspection
enable_introspection=$found_introspection
],dnl
[dnl
AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
])dnl
AC_MSG_RESULT([$found_introspection])
INTROSPECTION_SCANNER=
INTROSPECTION_COMPILER=
INTROSPECTION_GENERATE=
INTROSPECTION_GIRDIR=
INTROSPECTION_TYPELIBDIR=
if test "x$found_introspection" = "xyes"; then
INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
fi
AC_SUBST(INTROSPECTION_SCANNER)
AC_SUBST(INTROSPECTION_COMPILER)
AC_SUBST(INTROSPECTION_GENERATE)
AC_SUBST(INTROSPECTION_GIRDIR)
AC_SUBST(INTROSPECTION_TYPELIBDIR)
AC_SUBST(INTROSPECTION_CFLAGS)
AC_SUBST(INTROSPECTION_LIBS)
AC_SUBST(INTROSPECTION_MAKEFILE)
AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
])
dnl Usage:
dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
[
_GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
])
dnl Usage:
dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
[
_GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
])

View File

@ -0,0 +1,652 @@
#! /bin/sh
# Copyright (C) 2011-2013 Free Software Foundation, Inc.
#
# 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, 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, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
scriptversion=2011-12-27.17; # UTC
# Make unconditional expansion of undefined variables an error. This
# helps a lot in preventing typo-related bugs.
set -u
me=tap-driver.sh
fatal ()
{
echo "$me: fatal: $*" >&2
exit 1
}
usage_error ()
{
echo "$me: $*" >&2
print_usage >&2
exit 2
}
print_usage ()
{
cat <<END
Usage:
tap-driver.sh --test-name=NAME --log-file=PATH --trs-file=PATH
[--expect-failure={yes|no}] [--color-tests={yes|no}]
[--enable-hard-errors={yes|no}] [--ignore-exit]
[--diagnostic-string=STRING] [--merge|--no-merge]
[--comments|--no-comments] [--] TEST-COMMAND
The \`--test-name', \`--log-file' and \`--trs-file' options are mandatory.
END
}
# TODO: better error handling in option parsing (in particular, ensure
# TODO: $log_file, $trs_file and $test_name are defined).
test_name= # Used for reporting.
log_file= # Where to save the result and output of the test script.
trs_file= # Where to save the metadata of the test run.
expect_failure=0
color_tests=0
merge=0
ignore_exit=0
comments=0
diag_string='#'
while test $# -gt 0; do
case $1 in
--help) print_usage; exit $?;;
--version) echo "$me $scriptversion"; exit $?;;
--test-name) test_name=$2; shift;;
--log-file) log_file=$2; shift;;
--trs-file) trs_file=$2; shift;;
--color-tests) color_tests=$2; shift;;
--expect-failure) expect_failure=$2; shift;;
--enable-hard-errors) shift;; # No-op.
--merge) merge=1;;
--no-merge) merge=0;;
--ignore-exit) ignore_exit=1;;
--comments) comments=1;;
--no-comments) comments=0;;
--diagnostic-string) diag_string=$2; shift;;
--) shift; break;;
-*) usage_error "invalid option: '$1'";;
esac
shift
done
test $# -gt 0 || usage_error "missing test command"
case $expect_failure in
yes) expect_failure=1;;
*) expect_failure=0;;
esac
if test $color_tests = yes; then
init_colors='
color_map["red"]="" # Red.
color_map["grn"]="" # Green.
color_map["lgn"]="" # Light green.
color_map["blu"]="" # Blue.
color_map["mgn"]="" # Magenta.
color_map["std"]="" # No color.
color_for_result["ERROR"] = "mgn"
color_for_result["PASS"] = "grn"
color_for_result["XPASS"] = "red"
color_for_result["FAIL"] = "red"
color_for_result["XFAIL"] = "lgn"
color_for_result["SKIP"] = "blu"'
else
init_colors=''
fi
# :; is there to work around a bug in bash 3.2 (and earlier) which
# does not always set '$?' properly on redirection failure.
# See the Autoconf manual for more details.
:;{
(
# Ignore common signals (in this subshell only!), to avoid potential
# problems with Korn shells. Some Korn shells are known to propagate
# to themselves signals that have killed a child process they were
# waiting for; this is done at least for SIGINT (and usually only for
# it, in truth). Without the `trap' below, such a behaviour could
# cause a premature exit in the current subshell, e.g., in case the
# test command it runs gets terminated by a SIGINT. Thus, the awk
# script we are piping into would never seen the exit status it
# expects on its last input line (which is displayed below by the
# last `echo $?' statement), and would thus die reporting an internal
# error.
# For more information, see the Autoconf manual and the threads:
# <http://lists.gnu.org/archive/html/bug-autoconf/2011-09/msg00004.html>
# <http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/004121.html>
trap : 1 3 2 13 15
if test $merge -gt 0; then
exec 2>&1
else
exec 2>&3
fi
"$@"
echo $?
) | LC_ALL=C ${AM_TAP_AWK-awk} \
-v me="$me" \
-v test_script_name="$test_name" \
-v log_file="$log_file" \
-v trs_file="$trs_file" \
-v expect_failure="$expect_failure" \
-v merge="$merge" \
-v ignore_exit="$ignore_exit" \
-v comments="$comments" \
-v diag_string="$diag_string" \
'
# FIXME: the usages of "cat >&3" below could be optimized when using
# FIXME: GNU awk, and/on on systems that supports /dev/fd/.
# Implementation note: in what follows, `result_obj` will be an
# associative array that (partly) simulates a TAP result object
# from the `TAP::Parser` perl module.
## ----------- ##
## FUNCTIONS ##
## ----------- ##
function fatal(msg)
{
print me ": " msg | "cat >&2"
exit 1
}
function abort(where)
{
fatal("internal error " where)
}
# Convert a boolean to a "yes"/"no" string.
function yn(bool)
{
return bool ? "yes" : "no";
}
function add_test_result(result)
{
if (!test_results_index)
test_results_index = 0
test_results_list[test_results_index] = result
test_results_index += 1
test_results_seen[result] = 1;
}
# Whether the test script should be re-run by "make recheck".
function must_recheck()
{
for (k in test_results_seen)
if (k != "XFAIL" && k != "PASS" && k != "SKIP")
return 1
return 0
}
# Whether the content of the log file associated to this test should
# be copied into the "global" test-suite.log.
function copy_in_global_log()
{
for (k in test_results_seen)
if (k != "PASS")
return 1
return 0
}
# FIXME: this can certainly be improved ...
function get_global_test_result()
{
if ("ERROR" in test_results_seen)
return "ERROR"
if ("FAIL" in test_results_seen || "XPASS" in test_results_seen)
return "FAIL"
all_skipped = 1
for (k in test_results_seen)
if (k != "SKIP")
all_skipped = 0
if (all_skipped)
return "SKIP"
return "PASS";
}
function stringify_result_obj(result_obj)
{
if (result_obj["is_unplanned"] || result_obj["number"] != testno)
return "ERROR"
if (plan_seen == LATE_PLAN)
return "ERROR"
if (result_obj["directive"] == "TODO")
return result_obj["is_ok"] ? "XPASS" : "XFAIL"
if (result_obj["directive"] == "SKIP")
return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL;
if (length(result_obj["directive"]))
abort("in function stringify_result_obj()")
return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL
}
function decorate_result(result)
{
color_name = color_for_result[result]
if (color_name)
return color_map[color_name] "" result "" color_map["std"]
# If we are not using colorized output, or if we do not know how
# to colorize the given result, we should return it unchanged.
return result
}
function report(result, details)
{
if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/)
{
msg = ": " test_script_name
add_test_result(result)
}
else if (result == "#")
{
msg = " " test_script_name ":"
}
else
{
abort("in function report()")
}
if (length(details))
msg = msg " " details
# Output on console might be colorized.
print decorate_result(result) msg
# Log the result in the log file too, to help debugging (this is
# especially true when said result is a TAP error or "Bail out!").
print result msg | "cat >&3";
}
function testsuite_error(error_message)
{
report("ERROR", "- " error_message)
}
function handle_tap_result()
{
details = result_obj["number"];
if (length(result_obj["description"]))
details = details " " result_obj["description"]
if (plan_seen == LATE_PLAN)
{
details = details " # AFTER LATE PLAN";
}
else if (result_obj["is_unplanned"])
{
details = details " # UNPLANNED";
}
else if (result_obj["number"] != testno)
{
details = sprintf("%s # OUT-OF-ORDER (expecting %d)",
details, testno);
}
else if (result_obj["directive"])
{
details = details " # " result_obj["directive"];
if (length(result_obj["explanation"]))
details = details " " result_obj["explanation"]
}
report(stringify_result_obj(result_obj), details)
}
# `skip_reason` should be empty whenever planned > 0.
function handle_tap_plan(planned, skip_reason)
{
planned += 0 # Avoid getting confused if, say, `planned` is "00"
if (length(skip_reason) && planned > 0)
abort("in function handle_tap_plan()")
if (plan_seen)
{
# Error, only one plan per stream is acceptable.
testsuite_error("multiple test plans")
return;
}
planned_tests = planned
# The TAP plan can come before or after *all* the TAP results; we speak
# respectively of an "early" or a "late" plan. If we see the plan line
# after at least one TAP result has been seen, assume we have a late
# plan; in this case, any further test result seen after the plan will
# be flagged as an error.
plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN)
# If testno > 0, we have an error ("too many tests run") that will be
# automatically dealt with later, so do not worry about it here. If
# $plan_seen is true, we have an error due to a repeated plan, and that
# has already been dealt with above. Otherwise, we have a valid "plan
# with SKIP" specification, and should report it as a particular kind
# of SKIP result.
if (planned == 0 && testno == 0)
{
if (length(skip_reason))
skip_reason = "- " skip_reason;
report("SKIP", skip_reason);
}
}
function extract_tap_comment(line)
{
if (index(line, diag_string) == 1)
{
# Strip leading `diag_string` from `line`.
line = substr(line, length(diag_string) + 1)
# And strip any leading and trailing whitespace left.
sub("^[ \t]*", "", line)
sub("[ \t]*$", "", line)
# Return what is left (if any).
return line;
}
return "";
}
# When this function is called, we know that line is a TAP result line,
# so that it matches the (perl) RE "^(not )?ok\b".
function setup_result_obj(line)
{
# Get the result, and remove it from the line.
result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0)
sub("^(not )?ok[ \t]*", "", line)
# If the result has an explicit number, get it and strip it; otherwise,
# automatically assing the next progresive number to it.
if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/)
{
match(line, "^[0-9]+")
# The final `+ 0` is to normalize numbers with leading zeros.
result_obj["number"] = substr(line, 1, RLENGTH) + 0
line = substr(line, RLENGTH + 1)
}
else
{
result_obj["number"] = testno
}
if (plan_seen == LATE_PLAN)
# No further test results are acceptable after a "late" TAP plan
# has been seen.
result_obj["is_unplanned"] = 1
else if (plan_seen && testno > planned_tests)
result_obj["is_unplanned"] = 1
else
result_obj["is_unplanned"] = 0
# Strip trailing and leading whitespace.
sub("^[ \t]*", "", line)
sub("[ \t]*$", "", line)
# This will have to be corrected if we have a "TODO"/"SKIP" directive.
result_obj["description"] = line
result_obj["directive"] = ""
result_obj["explanation"] = ""
if (index(line, "#") == 0)
return # No possible directive, nothing more to do.
# Directives are case-insensitive.
rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*"
# See whether we have the directive, and if yes, where.
pos = match(line, rx "$")
if (!pos)
pos = match(line, rx "[^a-zA-Z0-9_]")
# If there was no TAP directive, we have nothing more to do.
if (!pos)
return
# Let`s now see if the TAP directive has been escaped. For example:
# escaped: ok \# SKIP
# not escaped: ok \\# SKIP
# escaped: ok \\\\\# SKIP
# not escaped: ok \ # SKIP
if (substr(line, pos, 1) == "#")
{
bslash_count = 0
for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--)
bslash_count += 1
if (bslash_count % 2)
return # Directive was escaped.
}
# Strip the directive and its explanation (if any) from the test
# description.
result_obj["description"] = substr(line, 1, pos - 1)
# Now remove the test description from the line, that has been dealt
# with already.
line = substr(line, pos)
# Strip the directive, and save its value (normalized to upper case).
sub("^[ \t]*#[ \t]*", "", line)
result_obj["directive"] = toupper(substr(line, 1, 4))
line = substr(line, 5)
# Now get the explanation for the directive (if any), with leading
# and trailing whitespace removed.
sub("^[ \t]*", "", line)
sub("[ \t]*$", "", line)
result_obj["explanation"] = line
}
function get_test_exit_message(status)
{
if (status == 0)
return ""
if (status !~ /^[1-9][0-9]*$/)
abort("getting exit status")
if (status < 127)
exit_details = ""
else if (status == 127)
exit_details = " (command not found?)"
else if (status >= 128 && status <= 255)
exit_details = sprintf(" (terminated by signal %d?)", status - 128)
else if (status > 256 && status <= 384)
# We used to report an "abnormal termination" here, but some Korn
# shells, when a child process die due to signal number n, can leave
# in $? an exit status of 256+n instead of the more standard 128+n.
# Apparently, both behaviours are allowed by POSIX (2008), so be
# prepared to handle them both. See also Austing Group report ID
# 0000051 <http://www.austingroupbugs.net/view.php?id=51>
exit_details = sprintf(" (terminated by signal %d?)", status - 256)
else
# Never seen in practice.
exit_details = " (abnormal termination)"
return sprintf("exited with status %d%s", status, exit_details)
}
function write_test_results()
{
print ":global-test-result: " get_global_test_result() > trs_file
print ":recheck: " yn(must_recheck()) > trs_file
print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file
for (i = 0; i < test_results_index; i += 1)
print ":test-result: " test_results_list[i] > trs_file
close(trs_file);
}
BEGIN {
## ------- ##
## SETUP ##
## ------- ##
'"$init_colors"'
# Properly initialized once the TAP plan is seen.
planned_tests = 0
COOKED_PASS = expect_failure ? "XPASS": "PASS";
COOKED_FAIL = expect_failure ? "XFAIL": "FAIL";
# Enumeration-like constants to remember which kind of plan (if any)
# has been seen. It is important that NO_PLAN evaluates "false" as
# a boolean.
NO_PLAN = 0
EARLY_PLAN = 1
LATE_PLAN = 2
testno = 0 # Number of test results seen so far.
bailed_out = 0 # Whether a "Bail out!" directive has been seen.
# Whether the TAP plan has been seen or not, and if yes, which kind
# it is ("early" is seen before any test result, "late" otherwise).
plan_seen = NO_PLAN
## --------- ##
## PARSING ##
## --------- ##
is_first_read = 1
while (1)
{
# Involutions required so that we are able to read the exit status
# from the last input line.
st = getline
if (st < 0) # I/O error.
fatal("I/O error while reading from input stream")
else if (st == 0) # End-of-input
{
if (is_first_read)
abort("in input loop: only one input line")
break
}
if (is_first_read)
{
is_first_read = 0
nextline = $0
continue
}
else
{
curline = nextline
nextline = $0
$0 = curline
}
# Copy any input line verbatim into the log file.
print | "cat >&3"
# Parsing of TAP input should stop after a "Bail out!" directive.
if (bailed_out)
continue
# TAP test result.
if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/)
{
testno += 1
setup_result_obj($0)
handle_tap_result()
}
# TAP plan (normal or "SKIP" without explanation).
else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/)
{
# The next two lines will put the number of planned tests in $0.
sub("^1\\.\\.", "")
sub("[^0-9]*$", "")
handle_tap_plan($0, "")
continue
}
# TAP "SKIP" plan, with an explanation.
else if ($0 ~ /^1\.\.0+[ \t]*#/)
{
# The next lines will put the skip explanation in $0, stripping
# any leading and trailing whitespace. This is a little more
# tricky in truth, since we want to also strip a potential leading
# "SKIP" string from the message.
sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "")
sub("[ \t]*$", "");
handle_tap_plan(0, $0)
}
# "Bail out!" magic.
# Older versions of prove and TAP::Harness (e.g., 3.17) did not
# recognize a "Bail out!" directive when preceded by leading
# whitespace, but more modern versions (e.g., 3.23) do. So we
# emulate the latter, "more modern" behaviour.
else if ($0 ~ /^[ \t]*Bail out!/)
{
bailed_out = 1
# Get the bailout message (if any), with leading and trailing
# whitespace stripped. The message remains stored in `$0`.
sub("^[ \t]*Bail out![ \t]*", "");
sub("[ \t]*$", "");
# Format the error message for the
bailout_message = "Bail out!"
if (length($0))
bailout_message = bailout_message " " $0
testsuite_error(bailout_message)
}
# Maybe we have too look for dianogtic comments too.
else if (comments != 0)
{
comment = extract_tap_comment($0);
if (length(comment))
report("#", comment);
}
}
## -------- ##
## FINISH ##
## -------- ##
# A "Bail out!" directive should cause us to ignore any following TAP
# error, as well as a non-zero exit status from the TAP producer.
if (!bailed_out)
{
if (!plan_seen)
{
testsuite_error("missing test plan")
}
else if (planned_tests != testno)
{
bad_amount = testno > planned_tests ? "many" : "few"
testsuite_error(sprintf("too %s tests run (expected %d, got %d)",
bad_amount, planned_tests, testno))
}
if (!ignore_exit)
{
# Fetch exit status from the last line.
exit_message = get_test_exit_message(nextline)
if (exit_message)
testsuite_error(exit_message)
}
}
write_test_results()
exit 0
} # End of "BEGIN" block.
'
# TODO: document that we consume the file descriptor 3 :-(
} 3>"$log_file"
test $? -eq 0 || fatal "I/O or internal error"
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

View File

@ -0,0 +1,5 @@
#! /bin/sh
# run a GTest in tap mode. The test binary is passed as $1
$1 -k --tap

710
clutter/clutter/Makefile.am Normal file
View File

@ -0,0 +1,710 @@
AUTOMAKE_OPTIONS = subdir-objects
# preamble
NULL =
# common definitions
CLEANFILES =
DISTCLEANFILES =
EXTRA_DIST =
BUILT_SOURCES =
AM_CPPFLAGS = \
-DCLUTTER_SYSCONFDIR=\""$(sysconfdir)"\" \
-DCLUTTER_COMPILATION=1 \
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
-DG_LOG_DOMAIN=\"Clutter\" \
-fvisibility=hidden \
-I$(top_srcdir) \
-I$(top_srcdir)/clutter \
-I$(top_builddir) \
-I$(top_builddir)/clutter \
-I$(top_srcdir)/../cogl \
-I$(top_builddir)/../cogl \
-I$(top_builddir)/../cogl/cogl \
$(CLUTTER_DEPRECATED_CFLAGS) \
$(CLUTTER_DEBUG_CFLAGS) \
$(NULL)
AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS)
# these are the gir files we generate using g-ir-scanner
INTROSPECTION_GIRS =
# the base include path for headers
clutter_base_includedir = $(includedir)/mutter-$(LIBMUTTER_API_VERSION)/clutter
clutter_includedir = $(clutter_base_includedir)/clutter
clutter_deprecateddir = $(clutter_base_includedir)/clutter/deprecated
# pkg-config files
pc_files =
# common sources - please, keep these sorted alphabetically
source_h = \
clutter-action.h \
clutter-actor-meta.h \
clutter-actor.h \
clutter-align-constraint.h \
clutter-animatable.h \
clutter-backend.h \
clutter-bind-constraint.h \
clutter-binding-pool.h \
clutter-bin-layout.h \
clutter-blur-effect.h \
clutter-box-layout.h \
clutter-brightness-contrast-effect.h \
clutter-cairo.h \
clutter-canvas.h \
clutter-child-meta.h \
clutter-click-action.h \
clutter-clone.h \
clutter-color-static.h \
clutter-color.h \
clutter-colorize-effect.h \
clutter-constraint.h \
clutter-container.h \
clutter-content.h \
clutter-deform-effect.h \
clutter-deprecated.h \
clutter-desaturate-effect.h \
clutter-device-manager.h \
clutter-drag-action.h \
clutter-drop-action.h \
clutter-effect.h \
clutter-enums.h \
clutter-event.h \
clutter-feature.h \
clutter-fixed-layout.h \
clutter-flow-layout.h \
clutter-gesture-action.h \
clutter-grid-layout.h \
clutter-group.h \
clutter-image.h \
clutter-input-device.h \
clutter-input-device-tool.h \
clutter-input-focus.h \
clutter-input-method.h \
clutter-interval.h \
clutter-keyframe-transition.h \
clutter-keysyms.h \
clutter-layout-manager.h \
clutter-layout-meta.h \
clutter-macros.h \
clutter-main.h \
clutter-offscreen-effect.h \
clutter-page-turn-effect.h \
clutter-paint-nodes.h \
clutter-paint-node.h \
clutter-pan-action.h \
clutter-path-constraint.h \
clutter-path.h \
clutter-property-transition.h \
clutter-rotate-action.h \
clutter-script.h \
clutter-scriptable.h \
clutter-scroll-actor.h \
clutter-settings.h \
clutter-shader-effect.h \
clutter-shader-types.h \
clutter-swipe-action.h \
clutter-snap-constraint.h \
clutter-stage.h \
clutter-stage-manager.h \
clutter-tap-action.h \
clutter-test-utils.h \
clutter-texture.h \
clutter-text.h \
clutter-text-buffer.h \
clutter-timeline.h \
clutter-transition-group.h \
clutter-transition.h \
clutter-types.h \
clutter-units.h \
clutter-virtual-input-device.h \
clutter-zoom-action.h \
$(NULL)
source_c = \
clutter-action.c \
clutter-actor-box.c \
clutter-actor-meta.c \
clutter-actor.c \
clutter-align-constraint.c \
clutter-animatable.c \
clutter-backend.c \
clutter-base-types.c \
clutter-bezier.c \
clutter-bind-constraint.c \
clutter-binding-pool.c \
clutter-bin-layout.c \
clutter-blur-effect.c \
clutter-box-layout.c \
clutter-brightness-contrast-effect.c \
clutter-cairo.c \
clutter-canvas.c \
clutter-child-meta.c \
clutter-click-action.c \
clutter-clone.c \
clutter-color.c \
clutter-colorize-effect.c \
clutter-constraint.c \
clutter-container.c \
clutter-content.c \
clutter-deform-effect.c \
clutter-desaturate-effect.c \
clutter-device-manager.c \
clutter-drag-action.c \
clutter-drop-action.c \
clutter-effect.c \
clutter-event.c \
clutter-feature.c \
clutter-fixed-layout.c \
clutter-flatten-effect.c \
clutter-flow-layout.c \
clutter-gesture-action.c \
clutter-grid-layout.c \
clutter-image.c \
clutter-input-device.c \
clutter-input-device-tool.c \
clutter-input-focus.c \
clutter-input-method.c \
clutter-virtual-input-device.c \
clutter-interval.c \
clutter-keyframe-transition.c \
clutter-keysyms-table.c \
clutter-layout-manager.c \
clutter-layout-meta.c \
clutter-main.c \
clutter-master-clock.c \
clutter-master-clock-default.c \
clutter-offscreen-effect.c \
clutter-page-turn-effect.c \
clutter-paint-nodes.c \
clutter-paint-node.c \
clutter-pan-action.c \
clutter-path-constraint.c \
clutter-path.c \
clutter-property-transition.c \
clutter-rotate-action.c \
clutter-script.c \
clutter-script-parser.c \
clutter-scriptable.c \
clutter-scroll-actor.c \
clutter-settings.c \
clutter-shader-effect.c \
clutter-shader-types.c \
clutter-swipe-action.c \
clutter-snap-constraint.c \
clutter-stage.c \
clutter-stage-manager.c \
clutter-stage-window.c \
clutter-tap-action.c \
clutter-test-utils.c \
clutter-text.c \
clutter-text-buffer.c \
clutter-transition-group.c \
clutter-transition.c \
clutter-timeline.c \
clutter-units.c \
clutter-util.c \
clutter-paint-volume.c \
clutter-zoom-action.c \
$(NULL)
# private headers; these should not be distributed or introspected
source_h_priv = \
clutter-actor-meta-private.h \
clutter-actor-private.h \
clutter-backend-private.h \
clutter-bezier.h \
clutter-constraint-private.h \
clutter-content-private.h \
clutter-debug.h \
clutter-device-manager-private.h \
clutter-easing.h \
clutter-effect-private.h \
clutter-event-translator.h \
clutter-event-private.h \
clutter-flatten-effect.h \
clutter-gesture-action-private.h \
clutter-id-pool.h \
clutter-input-focus-private.h \
clutter-input-method-private.h \
clutter-master-clock.h \
clutter-master-clock-default.h \
clutter-offscreen-effect-private.h \
clutter-paint-node-private.h \
clutter-paint-volume-private.h \
clutter-private.h \
clutter-script-private.h \
clutter-settings-private.h \
clutter-stage-manager-private.h \
clutter-stage-private.h \
clutter-stage-view.h \
clutter-stage-window.h \
$(NULL)
# private source code; these should not be introspected
source_c_priv = \
clutter-easing.c \
clutter-event-translator.c \
clutter-id-pool.c \
clutter-stage-view.c \
$(NULL)
# deprecated installed headers
deprecated_h = \
deprecated/clutter-actor.h \
deprecated/clutter-alpha.h \
deprecated/clutter-animatable.h \
deprecated/clutter-animation.h \
deprecated/clutter-animator.h \
deprecated/clutter-backend.h \
deprecated/clutter-behaviour.h \
deprecated/clutter-behaviour-depth.h \
deprecated/clutter-behaviour-ellipse.h \
deprecated/clutter-behaviour-opacity.h \
deprecated/clutter-behaviour-path.h \
deprecated/clutter-behaviour-rotate.h \
deprecated/clutter-behaviour-scale.h \
deprecated/clutter-bin-layout.h \
deprecated/clutter-box.h \
deprecated/clutter-cairo-texture.h \
deprecated/clutter-container.h \
deprecated/clutter-frame-source.h \
deprecated/clutter-group.h \
deprecated/clutter-input-device.h \
deprecated/clutter-keysyms.h \
deprecated/clutter-list-model.h \
deprecated/clutter-main.h \
deprecated/clutter-media.h \
deprecated/clutter-model.h \
deprecated/clutter-rectangle.h \
deprecated/clutter-score.h \
deprecated/clutter-shader.h \
deprecated/clutter-stage-manager.h \
deprecated/clutter-stage.h \
deprecated/clutter-state.h \
deprecated/clutter-table-layout.h \
deprecated/clutter-texture.h \
deprecated/clutter-timeline.h \
deprecated/clutter-timeout-pool.h \
deprecated/clutter-util.h \
$(NULL)
# deprecated source code
deprecated_c = \
deprecated/clutter-actor-deprecated.c \
deprecated/clutter-alpha.c \
deprecated/clutter-animation.c \
deprecated/clutter-animator.c \
deprecated/clutter-behaviour.c \
deprecated/clutter-behaviour-depth.c \
deprecated/clutter-behaviour-ellipse.c \
deprecated/clutter-behaviour-opacity.c \
deprecated/clutter-behaviour-path.c \
deprecated/clutter-behaviour-rotate.c \
deprecated/clutter-behaviour-scale.c \
deprecated/clutter-box.c \
deprecated/clutter-cairo-texture.c \
deprecated/clutter-frame-source.c \
deprecated/clutter-group.c \
deprecated/clutter-input-device-deprecated.c \
deprecated/clutter-layout-manager-deprecated.c \
deprecated/clutter-list-model.c \
deprecated/clutter-media.c \
deprecated/clutter-model.c \
deprecated/clutter-rectangle.c \
deprecated/clutter-score.c \
deprecated/clutter-shader.c \
deprecated/clutter-state.c \
deprecated/clutter-table-layout.c \
deprecated/clutter-texture.c \
deprecated/clutter-timeout-pool.c \
$(NULL)
# deprecated private headers; these should not be installed
deprecated_h_priv = \
deprecated/clutter-model-private.h \
deprecated/clutter-timeout-interval.h \
$(NULL)
# deprecated private source code; these should not be introspected
deprecated_c_priv = \
deprecated/clutter-timeout-interval.c \
$(NULL)
# built sources
built_source_c = \
clutter-enum-types.c \
clutter-marshal.c \
$(NULL)
# built headers
built_source_h = \
clutter-enum-types.h \
clutter-marshal.h \
$(NULL)
# config header
DISTCLEANFILES += clutter-config.h
EXTRA_DIST += clutter-config.h.in
# key symbol update script
EXTRA_DIST += clutter-keysyms-update.pl
pc_files += mutter-clutter-$(LIBMUTTER_API_VERSION).pc
# in order to be compatible with Clutter < 1.10, when we shipped a single
# shared library whose name was determined by the single backend it
# supported, we need to install symbolic links so that existing applications
# using Clutter won't break in the Brave New World of multi-backend support
# in the same shared object.
compat_libs =
# backends source listings
#
# backend_source_c := source code
# backend_source_h := installed public headers
# backend_source_c_priv := source that should not be scanned by g-i
# backend_source_h_priv := private headers
# backend_source_built := built sources
#
backend_source_c =
backend_source_h =
backend_source_c_priv =
backend_source_h_priv =
backend_source_built =
# X11 backend rules
x11_source_c = \
x11/clutter-backend-x11.c \
x11/clutter-device-manager-core-x11.c \
x11/clutter-event-x11.c \
x11/clutter-input-device-core-x11.c \
x11/clutter-keymap-x11.c \
x11/clutter-stage-x11.c \
x11/clutter-x11-texture-pixmap.c \
x11/clutter-xkb-a11y-x11.c \
$(NULL)
x11_source_h = \
x11/clutter-x11.h \
x11/clutter-x11-texture-pixmap.h \
$(NULL)
x11_source_h_priv = \
x11/clutter-backend-x11.h \
x11/clutter-device-manager-core-x11.h \
x11/clutter-input-device-core-x11.h \
x11/clutter-keymap-x11.h \
x11/clutter-settings-x11.h \
x11/clutter-stage-x11.h \
x11/clutter-xkb-a11y-x11.h \
$(NULL)
x11_source_c_priv = \
x11/xsettings/xsettings-client.c \
x11/xsettings/xsettings-client.h \
x11/xsettings/xsettings-common.c \
x11/xsettings/xsettings-common.h \
$(NULL)
x11_source_c += \
x11/clutter-device-manager-xi2.c \
x11/clutter-input-device-xi2.c \
x11/clutter-input-device-tool-xi2.c \
$(NULL)
x11_source_h_priv += \
x11/clutter-device-manager-xi2.h \
x11/clutter-input-device-xi2.h \
x11/clutter-input-device-tool-xi2.h \
$(NULL)
x11_source_c += \
x11/clutter-virtual-input-device-x11.c \
$(NULL)
x11_source_h_priv += \
x11/clutter-virtual-input-device-x11.h \
$(NULL)
backend_source_h += $(x11_source_h)
backend_source_c += $(x11_source_c)
backend_source_h_priv += $(x11_source_h_priv)
backend_source_c_priv += $(x11_source_c_priv)
# the list of files we want to introspect on X11
x11_introspection = $(x11_source_c) $(x11_source_h)
clutterx11_includedir = $(clutter_includedir)/x11
clutterx11_include_HEADERS = $(x11_source_h)
mutter-clutter-x11-@LIBMUTTER_API_VERSION@.pc: mutter-clutter-$(LIBMUTTER_API_VERSION).pc
$(QUIET_GEN)cp -f $< $(@F)
pc_files += mutter-clutter-x11-$(LIBMUTTER_API_VERSION).pc
# Shared cogl backend files
cogl_source_h =
cogl_source_c = \
cogl/clutter-stage-cogl.c \
$(NULL)
cogl_source_h_priv = \
cogl/clutter-stage-cogl.h \
$(NULL)
cogl_source_c_priv =
backend_source_h += $(cogl_source_h)
backend_source_c += $(cogl_source_c)
backend_source_h_priv += $(cogl_source_h_priv)
backend_source_c_priv += $(cogl_source_c_priv)
backend_source_h += $(glx_source_h)
backend_source_c += $(glx_source_c)
evdev_c_priv = \
evdev/clutter-device-manager-evdev.c \
evdev/clutter-input-device-evdev.c \
evdev/clutter-seat-evdev.c \
evdev/clutter-virtual-input-device-evdev.c \
evdev/clutter-event-evdev.c \
evdev/clutter-input-device-tool-evdev.c \
$(NULL)
evdev_h_priv = \
evdev/clutter-device-manager-evdev.h \
evdev/clutter-input-device-evdev.h \
evdev/clutter-seat-evdev.h \
evdev/clutter-input-device-tool-evdev.h \
evdev/clutter-virtual-input-device-evdev.h \
$(NULL)
evdev_h = evdev/clutter-evdev.h
if SUPPORT_WAYLAND
backend_source_c_priv += $(evdev_c_priv)
backend_source_h_priv += $(evdev_h_priv)
backend_source_h += $(evdev_h)
backend_source_c += evdev/clutter-xkb-utils.c
backend_source_h_priv += evdev/clutter-xkb-utils.h
# EGL backend rules
egl_source_h = \
egl/clutter-egl-headers.h \
egl/clutter-egl.h \
$(NULL)
egl_source_h_priv = egl/clutter-backend-eglnative.h
egl_source_c = egl/clutter-backend-eglnative.c
wayland_compositor_source_h = \
wayland/clutter-wayland-compositor.h \
wayland/clutter-wayland-surface.h
backend_source_h += $(wayland_compositor_source_h)
backend_source_c += \
wayland/clutter-wayland-surface.c
backend_source_h += $(egl_source_h)
backend_source_c += $(egl_source_c)
backend_source_h_priv += $(egl_source_h_priv)
endif # SUPPORT_WAYLAND
# cally
cally_sources_h = \
cally/cally-actor.h \
cally/cally-clone.h \
cally/cally-factory.h \
cally/cally-group.h \
cally/cally.h \
cally/cally-main.h \
cally/cally-rectangle.h \
cally/cally-root.h \
cally/cally-stage.h \
cally/cally-text.h \
cally/cally-texture.h \
cally/cally-util.h \
$(NULL)
cally_sources_c = \
cally/cally-actor.c \
cally/cally.c \
cally/cally-clone.c \
cally/cally-group.c \
cally/cally-rectangle.c \
cally/cally-root.c \
cally/cally-stage.c \
cally/cally-text.c \
cally/cally-texture.c \
cally/cally-util.c \
$(NULL)
cally_sources_private = \
cally/cally-actor-private.h \
$(NULL)
cally_includedir = $(clutter_base_includedir)/cally
cally_include_HEADERS = $(cally_sources_h)
# general build rules:
# you should not need to modify anything below this point
# glib-genmarshal rules
glib_marshal_list = clutter-marshal.list
glib_marshal_prefix = _clutter_marshal
include $(srcdir)/Makefile.am.marshal
# glib-mkenums rules
glib_enum_h = clutter-enum-types.h
glib_enum_c = clutter-enum-types.c
glib_enum_headers = $(source_h) $(deprecated_h)
include $(srcdir)/Makefile.am.enums
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = $(pc_files)
DISTCLEANFILES += $(pc_files)
clutter_include_HEADERS = $(source_h) clutter.h clutter-autocleanups.h clutter-mutter.h
nodist_clutter_include_HEADERS = clutter-config.h $(built_source_h)
clutter_deprecated_HEADERS = $(deprecated_h)
mutterlibdir = $(libdir)/mutter-@LIBMUTTER_API_VERSION@
mutterlib_LTLIBRARIES = libmutter-clutter-@LIBMUTTER_API_VERSION@.la
libmutter_clutter_@LIBMUTTER_API_VERSION@_la_LIBADD = \
$(LIBM) \
$(CLUTTER_LIBS) \
$(top_builddir)/../cogl/cogl/libmutter-cogl-$(LIBMUTTER_API_VERSION).la \
$(top_builddir)/../cogl/cogl-pango/libmutter-cogl-pango-$(LIBMUTTER_API_VERSION).la \
$(top_builddir)/../cogl/cogl-path/libmutter-cogl-path-$(LIBMUTTER_API_VERSION).la \
$(NULL)
libmutter_clutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
$(backend_source_c) \
$(backend_source_h) \
$(backend_source_c_priv) \
$(backend_source_h_priv) \
$(source_c) \
$(source_h) \
$(source_c_priv) \
$(source_h_priv) \
$(deprecated_c) \
$(deprecated_h) \
$(deprecated_c_priv) \
$(deprecated_h_priv) \
$(cally_sources_c) \
$(cally_sources_h) \
$(cally_sources_private) \
$(NULL)
nodist_libmutter_clutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
$(backend_source_built) \
$(built_source_c) \
$(built_source_h)
libmutter_clutter_@LIBMUTTER_API_VERSION@_la_LDFLAGS = \
$(CLUTTER_LINK_FLAGS) \
$(CLUTTER_LT_LDFLAGS) \
-export-dynamic \
-rpath $(mutterlibdir) \
$(NULL)
install-exec-local:
test -z "$(mutterlibdir)" || $(MKDIR_P) "$(DESTDIR)$(mutterlibdir)"
for lib in `echo $(compat_libs)`; do \
(cd $(DESTDIR)$(mutterlibdir) && \
rm -f $$lib.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION); \
) ; \
(cd $(DESTDIR)$(mutterlibdir) && \
{ ln -s -f libmutter-clutter-$(LIBMUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib.0 || \
{ rm -f $$lib.0 && ln -s libmutter-clutter-$(LIBMUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib.0; }; \
} \
) ; \
(cd $(DESTDIR)$(mutterlibdir) && \
{ ln -s -f libmutter-clutter-$(LIBMUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib || \
{ rm -f $$lib && ln -s libmutter-clutter-$(LIBMUTTER_API_VERSION).so.0.$(CLUTTER_LT_CURRENT).$(CLUTTER_LT_REVISION) $$lib; }; \
} \
) ; \
done
# gobject-introspection rules
-include $(INTROSPECTION_MAKEFILE)
INTROSPECTION_SCANNER_ARGS = \
--add-include-path=$(top_builddir)/../cogl/cogl \
--add-include-path=$(top_builddir)/../cogl/cogl-pango
INTROSPECTION_COMPILER_ARGS = \
--includedir=$(top_builddir)/../cogl/cogl \
--includedir=$(top_builddir)/../cogl/cogl-pango
INTROSPECTION_SCANNER_ENV = \
PKG_CONFIG_PATH=$(top_builddir)/../cogl/cogl/:$(top_builddir)/../cogl/cogl-pango/:$${PKG_CONFIG_PATH}
Clutter-@LIBMUTTER_API_VERSION@.gir: libmutter-clutter-@LIBMUTTER_API_VERSION@.la Makefile
Clutter_@LIBMUTTER_API_VERSION@_gir_NAMESPACE = Clutter
Clutter_@LIBMUTTER_API_VERSION@_gir_VERSION = @LIBMUTTER_API_VERSION@
Clutter_@LIBMUTTER_API_VERSION@_gir_LIBS = libmutter-clutter-@LIBMUTTER_API_VERSION@.la
Clutter_@LIBMUTTER_API_VERSION@_gir_FILES = \
$(clutter_include_HEADERS) \
$(clutter_deprecated_HEADERS) \
$(nodist_clutter_include_HEADERS) \
$(source_c) \
$(deprecated_c) \
$(built_source_c)
Clutter_@LIBMUTTER_API_VERSION@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
Clutter_@LIBMUTTER_API_VERSION@_gir_INCLUDES = GL-1.0 GObject-2.0 cairo-1.0 Cogl-@LIBMUTTER_API_VERSION@ CoglPango-@LIBMUTTER_API_VERSION@ Atk-1.0 Json-1.0
Clutter_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
--warn-all \
--c-include='clutter/clutter.h' \
--pkg-export=mutter-clutter-@LIBMUTTER_API_VERSION@
INTROSPECTION_GIRS += Clutter-@LIBMUTTER_API_VERSION@.gir
Cally-@LIBMUTTER_API_VERSION@.gir: Makefile Clutter-@LIBMUTTER_API_VERSION@.gir
Cally_@LIBMUTTER_API_VERSION@_gir_NAMESPACE = Cally
Cally_@LIBMUTTER_API_VERSION@_gir_VERSION = @LIBMUTTER_API_VERSION@
Cally_@LIBMUTTER_API_VERSION@_gir_LIBS = libmutter-clutter-@LIBMUTTER_API_VERSION@.la
Cally_@LIBMUTTER_API_VERSION@_gir_FILES = $(cally_sources_h) $(cally_sources_c)
Cally_@LIBMUTTER_API_VERSION@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
Cally_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
--warn-all \
--c-include='cally/cally.h' \
--pkg-export=mutter-clutter-@LIBMUTTER_API_VERSION@ \
--include-uninstalled=$(top_builddir)/clutter/Clutter-@LIBMUTTER_API_VERSION@.gir
INTROSPECTION_GIRS += Cally-@LIBMUTTER_API_VERSION@.gir
ClutterX11-@LIBMUTTER_API_VERSION@.gir: Makefile Clutter-@LIBMUTTER_API_VERSION@.gir
ClutterX11_@LIBMUTTER_API_VERSION@_gir_NAMESPACE = ClutterX11
ClutterX11_@LIBMUTTER_API_VERSION@_gir_INCLUDES = xlib-2.0
ClutterX11_@LIBMUTTER_API_VERSION@_gir_LIBS = libmutter-clutter-@LIBMUTTER_API_VERSION@.la
ClutterX11_@LIBMUTTER_API_VERSION@_gir_FILES = $(x11_introspection)
ClutterX11_@LIBMUTTER_API_VERSION@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
ClutterX11_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
--warn-all \
--c-include='clutter/x11/clutter-x11.h' \
--pkg-export=mutter-clutter-x11-@LIBMUTTER_API_VERSION@ \
--include-uninstalled=$(top_builddir)/clutter/Clutter-@LIBMUTTER_API_VERSION@.gir
INTROSPECTION_GIRS += ClutterX11-@LIBMUTTER_API_VERSION@.gir
# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to
# install anything - we need to install inside our prefix.
girdir = $(mutterlibdir)
gir_DATA = $(INTROSPECTION_GIRS)
typelibdir = $(mutterlibdir)
typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
EXTRA_DIST += \
Makefile.am.marshal \
Makefile.am.enums
CLEANFILES += $(gir_DATA) $(typelib_DATA)

View File

@ -0,0 +1,52 @@
# Rules for generating enumeration types using glib-mkenums
#
# Define:
# glib_enum_h = header template file
# glib_enum_c = source template file
# glib_enum_headers = list of headers to parse
#
# before including Makefile.am.enums. You will also need to have
# the following targets already defined:
#
# CLEANFILES
# DISTCLEANFILES
# BUILT_SOURCES
# EXTRA_DIST
#
# Author: Emmanuele Bassi <ebassi@linux.intel.com>
# Basic sanity checks
$(if $(GLIB_MKENUMS),,$(error Need to define GLIB_MKENUMS))
$(if $(or $(glib_enum_h), \
$(glib_enum_c)),, \
$(error Need to define glib_enum_h and glib_enum_c))
$(if $(glib_enum_headers),,$(error Need to define glib_enum_headers))
enum_tmpl_h=$(addprefix $(srcdir)/, $(glib_enum_h:.h=.h.in))
enum_tmpl_c=$(addprefix $(srcdir)/, $(glib_enum_c:.c=.c.in))
enum_headers=$(addprefix $(srcdir)/, $(glib_enum_headers))
CLEANFILES += stamp-enum-types
DISTCLEANFILES += $(glib_enum_h) $(glib_enum_c)
BUILT_SOURCES += $(glib_enum_h) $(glib_enum_c)
EXTRA_DIST += $(enum_tmpl_h) $(enum_tmpl_c)
stamp-enum-types: $(enum_headers) $(enum_tmpl_h)
$(AM_V_GEN)$(GLIB_MKENUMS) \
--template $(enum_tmpl_h) \
$(enum_headers) > xgen-eh \
&& (cmp -s xgen-eh $(glib_enum_h) || cp -f xgen-eh $(glib_enum_h)) \
&& rm -f xgen-eh \
&& echo timestamp > $(@F)
$(glib_enum_h): stamp-enum-types
@true
$(glib_enum_c): $(enum_headers) $(enum_tmpl_h) $(enum_tmpl_c)
$(AM_V_GEN)$(GLIB_MKENUMS) \
--template $(enum_tmpl_c) \
$(enum_headers) > xgen-ec \
&& cp -f xgen-ec $(glib_enum_c) \
&& rm -f xgen-ec

View File

@ -0,0 +1,54 @@
# Rules for generating marshal files using glib-genmarshal
#
# Define:
# glib_marshal_list = marshal list file
# glib_marshal_prefix = prefix for marshal functions
#
# before including Makefile.am.marshal. You will also need to have
# the following targets already defined:
#
# CLEANFILES
# DISTCLEANFILES
# BUILT_SOURCES
# EXTRA_DIST
#
# Author: Emmanuele Bassi <ebassi@linux.intel.com>
# Basic sanity checks
$(if $(GLIB_GENMARSHAL),,$(error Need to define GLIB_GENMARSHAL))
$(if $(or $(glib_marshal_list), \
$(glib_marshal_prefix)),, \
$(error Need to define glib_marshal_list and glib_marshal_prefix))
marshal_h = $(glib_marshal_list:.list=.h)
marshal_c = $(glib_marshal_list:.list=.c)
marshal_list = $(addprefix $(srcdir)/, $(glib_marshal_list))
CLEANFILES += stamp-marshal
DISTCLEANFILES += $(marshal_h) $(marshal_c)
BUILT_SOURCES += $(marshal_h) $(marshal_c)
EXTRA_DIST += $(marshal_list)
stamp-marshal: $(marshal_list)
$(AM_V_GEN)$(GLIB_GENMARSHAL) \
--prefix=$(glib_marshal_prefix) \
--header \
--valist-marshallers \
$(marshal_list) > xgen-mh \
&& (cmp -s xgen-mh $(marshal_h) || cp -f xgen-mh $(marshal_h)) \
&& rm -f xgen-mh \
&& echo timestamp > $(@F)
$(marshal_h): stamp-marshal
@true
$(marshal_c): $(marshal_h)
$(AM_V_GEN)$(GLIB_GENMARSHAL) \
--prefix=$(glib_marshal_prefix) \
--body \
--valist-marshallers \
--prototypes \
$(marshal_list) > xgen-mc \
&& (cmp -s xgen-mc $(marshal_c) || cp -f xgen-mc $(marshal_c)) \
&& rm -f xgen-mc

View File

@ -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
*
*/

View File

@ -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>
@ -308,7 +310,11 @@ cally_actor_finalize (GObject *obj)
_cally_actor_clean_action_list (cally_actor);
g_clear_handle_id (&priv->action_idle_handler, g_source_remove);
if (priv->action_idle_handler)
{
g_source_remove (priv->action_idle_handler);
priv->action_idle_handler = 0;
}
if (priv->action_queue)
{
@ -598,11 +604,10 @@ cally_actor_real_remove_actor (ClutterActor *container,
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), 0);
atk_parent = ATK_OBJECT (data);
atk_child = clutter_actor_get_accessible (actor);
if (clutter_actor_has_accessible (actor))
if (atk_child)
{
atk_child = clutter_actor_get_accessible (actor);
g_value_init (&values.old_value, G_TYPE_POINTER);
g_value_set_pointer (&values.old_value, atk_parent);
@ -652,7 +657,7 @@ cally_actor_get_extents (AtkComponent *component,
ClutterActor *actor = NULL;
gint top_level_x, top_level_y;
gfloat f_width, f_height;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
ClutterActor *stage = NULL;
g_return_if_fail (CALLY_IS_ACTOR (component));
@ -732,7 +737,11 @@ cally_actor_grab_focus (AtkComponent *component)
*
* This gets the top level origin, it is, the position of the stage in
* the global screen. You can see it as the absolute display position
* of the stage. This is 0,0 for a compositor.
* of the stage.
*
* FIXME: only the case with x11 is implemented, other backends are
* required
*
*/
void
_cally_actor_get_top_level_origin (ClutterActor *actor,
@ -740,11 +749,54 @@ _cally_actor_get_top_level_origin (ClutterActor *actor,
gint *yp)
{
/* default values */
gint x = 0;
gint y = 0;
#ifdef CLUTTER_WINDOWING_X11
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
{
ClutterActor *stage = NULL;
Display *display = NULL;
Window root_window;
Window stage_window;
Window child;
gint return_val = 0;
stage = clutter_actor_get_stage (actor);
/* FIXME: what happens if you use another display with
clutter_backend_x11_set_display ?*/
display = clutter_x11_get_default_display ();
root_window = clutter_x11_get_root_window ();
stage_window = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
return_val = XTranslateCoordinates (display, stage_window, root_window,
0, 0, &x, &y,
&child);
if (!return_val)
g_warning ("[x11] We were not able to get proper absolute "
"position of the stage");
}
else
#endif
{
static gboolean yet_warned = FALSE;
if (!yet_warned)
{
yet_warned = TRUE;
g_warning ("The current Clutter backend does not support using "
"atk_component_get_extents() with ATK_XY_SCREEN.");
}
}
if (xp)
*xp = 0;
*xp = x;
if (yp)
*yp = 0;
*yp = y;
}
/* AtkAction implementation */
@ -765,11 +817,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 +828,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 +852,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 +1018,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;
@ -996,8 +1044,10 @@ _cally_actor_clean_action_list (CallyActor *cally_actor)
if (priv->action_list)
{
g_list_free_full (priv->action_list,
(GDestroyNotify) _cally_actor_destroy_action_info);
g_list_foreach (priv->action_list,
(GFunc) _cally_actor_destroy_action_info,
NULL);
g_list_free (priv->action_list);
priv->action_list = NULL;
}
}
@ -1086,7 +1136,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 +1156,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 +1190,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 +1241,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);
}

View File

@ -0,0 +1,147 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2008 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* Based on GailContainer from GAIL
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:cally-group
* @Title: CallyGroup
* @short_description: Implementation of the ATK interfaces for a #ClutterGroup
* @see_also: #ClutterGroup
*
* #CallyGroup implements the required ATK interfaces of #ClutterGroup
* In particular it exposes each of the Clutter actors contained in the
* group.
*/
#include "clutter-build-config.h"
#include "cally-group.h"
#include "cally-actor-private.h"
static gint cally_group_get_n_children (AtkObject *obj);
static AtkObject* cally_group_ref_child (AtkObject *obj,
gint i);
static void cally_group_real_initialize (AtkObject *obj,
gpointer data);
G_DEFINE_TYPE (CallyGroup, cally_group, CALLY_TYPE_ACTOR)
static void
cally_group_class_init (CallyGroupClass *klass)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->get_n_children = cally_group_get_n_children;
class->ref_child = cally_group_ref_child;
class->initialize = cally_group_real_initialize;
}
static void
cally_group_init (CallyGroup *group)
{
/* nothing to do yet */
}
/**
* cally_group_new:
* @actor: a #ClutterGroup
*
* Creates a #CallyGroup for @actor
*
* Return value: the newly created #CallyGroup
*
* Since: 1.4
*/
AtkObject *
cally_group_new (ClutterActor *actor)
{
GObject *object = NULL;
AtkObject *accessible = NULL;
g_return_val_if_fail (CLUTTER_IS_GROUP (actor), NULL);
object = g_object_new (CALLY_TYPE_GROUP, NULL);
accessible = ATK_OBJECT (object);
atk_object_initialize (accessible, actor);
return accessible;
}
static gint
cally_group_get_n_children (AtkObject *obj)
{
ClutterActor *actor = NULL;
gint count = 0;
g_return_val_if_fail (CALLY_IS_GROUP (obj), count);
actor = CALLY_GET_CLUTTER_ACTOR (obj);
if (actor == NULL) /* defunct */
return 0;
g_return_val_if_fail (CLUTTER_IS_GROUP(actor), count);
count = clutter_actor_get_n_children (actor);
return count;
}
static AtkObject*
cally_group_ref_child (AtkObject *obj,
gint i)
{
AtkObject *accessible = NULL;
ClutterActor *actor = NULL;
ClutterActor *child = NULL;
g_return_val_if_fail (CALLY_IS_GROUP (obj), NULL);
g_return_val_if_fail ((i >= 0), NULL);
actor = CALLY_GET_CLUTTER_ACTOR (obj);
g_return_val_if_fail (CLUTTER_IS_GROUP(actor), NULL);
child = clutter_actor_get_child_at_index (actor, i);
if (!child)
return NULL;
accessible = clutter_actor_get_accessible (child);
if (accessible != NULL)
g_object_ref (accessible);
return accessible;
}
static void
cally_group_real_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (cally_group_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_PANEL;
}

View File

@ -0,0 +1,87 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2008 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* Based on GailContainer from GAIL
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CALLY_GROUP_H__
#define __CALLY_GROUP_H__
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cally/cally.h> can be included directly."
#endif
#include <cally/cally-actor.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define CALLY_TYPE_GROUP (cally_group_get_type ())
#define CALLY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_GROUP, CallyGroup))
#define CALLY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_GROUP, CallyGroupClass))
#define CALLY_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_GROUP))
#define CALLY_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_GROUP))
#define CALLY_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_GROUP, CallyGroupClass))
typedef struct _CallyGroup CallyGroup;
typedef struct _CallyGroupClass CallyGroupClass;
typedef struct _CallyGroupPrivate CallyGroupPrivate;
/**
* CallyGroup:
*
* The <structname>CallyGroup</structname> structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _CallyGroup
{
/*< private >*/
CallyActor parent;
CallyGroupPrivate *priv;
};
/**
* CallyGroupClass:
*
* The <structname>CallyGroupClass</structname> structure contains only
* private data
*
* Since: 1.4
*/
struct _CallyGroupClass
{
/*< private >*/
CallyActorClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_EXPORT
GType cally_group_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
AtkObject* cally_group_new (ClutterActor *actor);
G_END_DECLS
#endif /* __CALLY_GROUP_H__ */

View File

@ -0,0 +1,98 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:cally-rectangle
* @short_description: Implementation of the ATK interfaces for a #ClutterRectangle
* @see_also: #ClutterRectangle
*
* #CallyRectangle implements the required ATK interfaces of #ClutterRectangle
*
* In particular it sets a proper role for the rectangle.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "cally-rectangle.h"
#include "cally-actor-private.h"
#include "clutter-color.h"
#include "deprecated/clutter-rectangle.h"
/* AtkObject */
static void cally_rectangle_real_initialize (AtkObject *obj,
gpointer data);
G_DEFINE_TYPE (CallyRectangle, cally_rectangle, CALLY_TYPE_ACTOR)
static void
cally_rectangle_class_init (CallyRectangleClass *klass)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->initialize = cally_rectangle_real_initialize;
}
static void
cally_rectangle_init (CallyRectangle *rectangle)
{
/* nothing to do yet */
}
/**
* cally_rectangle_new:
* @actor: a #ClutterActor
*
* Creates a new #CallyRectangle for the given @actor. @actor must be
* a #ClutterRectangle.
*
* Return value: the newly created #AtkObject
*
* Since: 1.4
*/
AtkObject*
cally_rectangle_new (ClutterActor *actor)
{
GObject *object = NULL;
AtkObject *accessible = NULL;
g_return_val_if_fail (CLUTTER_IS_RECTANGLE (actor), NULL);
object = g_object_new (CALLY_TYPE_RECTANGLE, NULL);
accessible = ATK_OBJECT (object);
atk_object_initialize (accessible, actor);
return accessible;
}
static void
cally_rectangle_real_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (cally_rectangle_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_IMAGE;
}

View File

@ -0,0 +1,84 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CALLY_RECTANGLE_H__
#define __CALLY_RECTANGLE_H__
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cally/cally.h> can be included directly."
#endif
#include <cally/cally-actor.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define CALLY_TYPE_RECTANGLE (cally_rectangle_get_type ())
#define CALLY_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_RECTANGLE, CallyRectangle))
#define CALLY_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_RECTANGLE, CallyRectangleClass))
#define CALLY_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_RECTANGLE))
#define CALLY_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_RECTANGLE))
#define CALLY_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_RECTANGLE, CallyRectangleClass))
typedef struct _CallyRectangle CallyRectangle;
typedef struct _CallyRectangleClass CallyRectangleClass;
typedef struct _CallyRectanglePrivate CallyRectanglePrivate;
/**
* CallyRectangle:
*
* The <structname>CallyRectangle</structname> structure contains only private
* data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _CallyRectangle
{
/*< private >*/
CallyActor parent;
CallyRectanglePrivate *priv;
};
/**
* CallyRectangleClass:
*
* The <structname>CallyRectangleClass</structname> structure contains
* only private data
*
* Since: 1.4
*/
struct _CallyRectangleClass
{
/*< private >*/
CallyActorClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_EXPORT
GType cally_rectangle_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
AtkObject* cally_rectangle_new (ClutterActor *actor);
G_END_DECLS
#endif /* __CALLY_RECTANGLE_H__ */

View File

@ -75,8 +75,8 @@ struct _CallyRootPrivate
GSList *stage_list;
/* signals id */
gulong stage_added_id;
gulong stage_removed_id;
guint stage_added_id;
guint stage_removed_id;
};
G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
@ -149,9 +149,11 @@ cally_root_finalize (GObject *object)
stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
g_clear_signal_handler (&root->priv->stage_added_id, stage_manager);
g_signal_handler_disconnect (stage_manager,
root->priv->stage_added_id);
g_clear_signal_handler (&root->priv->stage_removed_id, stage_manager);
g_signal_handler_disconnect (stage_manager,
root->priv->stage_added_id);
G_OBJECT_CLASS (cally_root_parent_class)->finalize (object);
}

View File

@ -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,
@ -63,7 +63,7 @@ struct _CallyStagePrivate
G_DEFINE_TYPE_WITH_CODE (CallyStage,
cally_stage,
CALLY_TYPE_ACTOR,
CALLY_TYPE_GROUP,
G_ADD_PRIVATE (CallyStage)
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
cally_stage_window_interface_init));
@ -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)

View File

@ -25,7 +25,7 @@
#error "Only <cally/cally.h> can be included directly."
#endif
#include <cally/cally-actor.h>
#include <cally/cally-group.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
@ -52,7 +52,7 @@ typedef struct _CallyStagePrivate CallyStagePrivate;
struct _CallyStage
{
/*< private >*/
CallyActor parent;
CallyGroup parent;
CallyStagePrivate *priv;
};
@ -68,7 +68,7 @@ struct _CallyStage
struct _CallyStageClass
{
/*< private >*/
CallyActorClass parent_class;
CallyGroupClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[16];

View File

@ -247,7 +247,11 @@ cally_text_finalize (GObject *obj)
/* g_object_unref (cally_text->priv->textutil); */
/* cally_text->priv->textutil = NULL; */
g_clear_handle_id (&cally_text->priv->insert_idle_handler, g_source_remove);
if (cally_text->priv->insert_idle_handler)
{
g_source_remove (cally_text->priv->insert_idle_handler);
cally_text->priv->insert_idle_handler = 0;
}
G_OBJECT_CLASS (cally_text_parent_class)->finalize (obj);
}
@ -1434,7 +1438,7 @@ static void cally_text_get_character_extents (AtkText *text,
PangoLayout *layout;
PangoRectangle extents;
const gchar *text_value;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
actor = CALLY_GET_CLUTTER_ACTOR (text);
if (actor == NULL) /* State is defunct */
@ -1513,7 +1517,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 +1556,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 +1657,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 +1870,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;
@ -2290,7 +2294,7 @@ _cally_misc_get_index_at_point (ClutterText *clutter_text,
gint index, x_window, y_window, x_toplevel, y_toplevel;
gint x_temp, y_temp;
gboolean ret;
graphene_point3d_t verts[4];
ClutterVertex verts[4];
PangoLayout *layout;
gint x_layout, y_layout;

View File

@ -0,0 +1,98 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:cally-texture
* @Title: CallyTexture
* @short_description: Implementation of the ATK interfaces for a #ClutterTexture
* @see_also: #ClutterTexture
*
* #CallyTexture implements the required ATK interfaces of #ClutterTexture
*
* In particular it sets a proper role for the texture.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "cally-texture.h"
#include "cally-actor-private.h"
#include "deprecated/clutter-texture.h"
/* AtkObject */
static void cally_texture_real_initialize (AtkObject *obj,
gpointer data);
G_DEFINE_TYPE (CallyTexture, cally_texture, CALLY_TYPE_ACTOR)
static void
cally_texture_class_init (CallyTextureClass *klass)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
class->initialize = cally_texture_real_initialize;
}
static void
cally_texture_init (CallyTexture *texture)
{
/* nothing to do yet */
}
/**
* cally_texture_new:
* @actor: a #ClutterActor
*
* Creates a new #CallyTexture for the given @actor. @actor must be
* a #ClutterTexture.
*
* Return value: the newly created #AtkObject
*
* Since: 1.4
*/
AtkObject*
cally_texture_new (ClutterActor *actor)
{
GObject *object = NULL;
AtkObject *accessible = NULL;
g_return_val_if_fail (CLUTTER_IS_TEXTURE (actor), NULL);
object = g_object_new (CALLY_TYPE_TEXTURE, NULL);
accessible = ATK_OBJECT (object);
atk_object_initialize (accessible, actor);
return accessible;
}
static void
cally_texture_real_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (cally_texture_parent_class)->initialize (obj, data);
/* default role */
obj->role = ATK_ROLE_IMAGE;
}

View File

@ -0,0 +1,84 @@
/* CALLY - The Clutter Accessibility Implementation Library
*
* Copyright (C) 2009 Igalia, S.L.
*
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CALLY_TEXTURE_H__
#define __CALLY_TEXTURE_H__
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cally/cally.h> can be included directly."
#endif
#include <clutter/clutter.h>
#include <cally/cally-actor.h>
G_BEGIN_DECLS
#define CALLY_TYPE_TEXTURE (cally_texture_get_type ())
#define CALLY_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_TEXTURE, CallyTexture))
#define CALLY_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_TEXTURE, CallyTextureClass))
#define CALLY_IS_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_TEXTURE))
#define CALLY_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_TEXTURE))
#define CALLY_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_TEXTURE, CallyTextureClass))
typedef struct _CallyTexture CallyTexture;
typedef struct _CallyTextureClass CallyTextureClass;
typedef struct _CallyTexturePrivate CallyTexturePrivate;
/**
* CallyTexture:
*
* The <structname>CallyTexture</structname> structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _CallyTexture
{
/*< private >*/
CallyActor parent;
CallyTexturePrivate *priv;
};
/**
* CallyTextureClass:
*
* The <structname>CallyTextureClass</structname> structure contains
* only private data
*
* Since: 1.4
*/
struct _CallyTextureClass
{
/*< private >*/
CallyActorClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_EXPORT
GType cally_texture_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
AtkObject *cally_texture_new (ClutterActor *actor);
G_END_DECLS
#endif /* __CALLY_TEXTURE_H__ */

View File

@ -36,8 +36,11 @@
#include "cally.h"
#include "cally-actor.h"
#include "cally-group.h"
#include "cally-stage.h"
#include "cally-text.h"
#include "cally-texture.h"
#include "cally-rectangle.h"
#include "cally-clone.h"
#include "cally-factory.h"
@ -50,8 +53,11 @@
/* factories initialization*/
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_GROUP, cally_group, cally_group_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_STAGE, cally_stage, cally_stage_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXTURE, cally_texture, cally_texture_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
/**
@ -69,8 +75,11 @@ cally_accessibility_init (void)
{
/* setting the factories */
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_GROUP, cally_group);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_STAGE, cally_stage);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXTURE, cally_texture);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_RECTANGLE, cally_rectangle);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone);
/* Initialize the CallyUtility class */

View File

@ -26,10 +26,13 @@
#include "cally-actor.h"
#include "cally-clone.h"
#include "cally-factory.h"
#include "cally-group.h"
#include "cally-main.h"
#include "cally-rectangle.h"
#include "cally-root.h"
#include "cally-stage.h"
#include "cally-text.h"
#include "cally-texture.h"
#include "cally-util.h"
#undef __CALLY_H_INSIDE__

View File

@ -33,11 +33,28 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_ACTION (clutter_action_get_type ())
#define CLUTTER_TYPE_ACTION (clutter_action_get_type ())
#define CLUTTER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTION, ClutterAction))
#define CLUTTER_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTION))
#define CLUTTER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTION, ClutterActionClass))
#define CLUTTER_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTION))
#define CLUTTER_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTION, ClutterActionClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterAction, clutter_action,
CLUTTER, ACTION, ClutterActorMeta);
typedef struct _ClutterActionClass ClutterActionClass;
/**
* ClutterAction:
*
* The #ClutterAction structure contains only private data and
* should be accessed using the provided API.
*
* Since: 1.4
*/
struct _ClutterAction
{
/*< private >*/
ClutterActorMeta parent_instance;
};
/**
* ClutterActionClass:
@ -61,6 +78,9 @@ struct _ClutterActionClass
void (* _clutter_action8) (void);
};
CLUTTER_EXPORT
GType clutter_action_get_type (void) G_GNUC_CONST;
/* ClutterActor API */
CLUTTER_EXPORT
void clutter_actor_add_action (ClutterActor *self,

View File

@ -1,12 +0,0 @@
#ifndef __CLUTTER_ACTOR_BOX_PRIVATE_H__
#define __CLUTTER_ACTOR_BOX_PRIVATE_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
void _clutter_actor_box_enlarge_for_effects (ClutterActorBox *box);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_BOX_PRIVATE_H__ */

View File

@ -5,7 +5,6 @@
#include "clutter-types.h"
#include "clutter-interval.h"
#include "clutter-private.h"
#include "clutter-actor-box-private.h"
/**
* clutter_actor_box_new:
@ -54,7 +53,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 +129,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 +147,7 @@ void
clutter_actor_box_free (ClutterActorBox *box)
{
if (G_LIKELY (box != NULL))
g_free (box);
g_slice_free (ClutterActorBox, box);
}
/**
@ -320,7 +319,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
*
@ -340,7 +339,7 @@ clutter_actor_box_contains (const ClutterActorBox *box,
/**
* clutter_actor_box_from_vertices:
* @box: a #ClutterActorBox
* @verts: (array fixed-size=4): array of four #graphene_point3d_t
* @verts: (array fixed-size=4): array of four #ClutterVertex
*
* Calculates the bounding box represented by the four vertices; for details
* of the vertex array see clutter_actor_get_abs_allocation_vertices().
@ -348,8 +347,8 @@ clutter_actor_box_contains (const ClutterActorBox *box,
* Since: 1.0
*/
void
clutter_actor_box_from_vertices (ClutterActorBox *box,
const graphene_point3d_t verts[])
clutter_actor_box_from_vertices (ClutterActorBox *box,
const ClutterVertex verts[])
{
gfloat x_1, x_2, y_1, y_2;
@ -543,104 +542,6 @@ clutter_actor_box_set_size (ClutterActorBox *box,
box->y2 = box->y1 + height;
}
void
_clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
{
float width, height;
/* The aim here is that for a given rectangle defined with floating point
* coordinates we want to determine a stable quantized size in pixels
* that doesn't vary due to the original box's sub-pixel position.
*
* The reason this is important is because effects will use this
* API to determine the size of offscreen framebuffers and so for
* a fixed-size object that may be animated across the screen we
* want to make sure that the stage paint-box has an equally stable
* size so that effects aren't made to continuously re-allocate
* a corresponding fbo.
*
* The other thing we consider is that the calculation of this box is
* subject to floating point precision issues that might be slightly
* different to the precision issues involved with actually painting the
* actor, which might result in painting slightly leaking outside the
* user's calculated paint-volume. For this we simply aim to pad out the
* paint-volume by at least half a pixel all the way around.
*/
width = box->x2 - box->x1;
height = box->y2 - box->y1;
width = CLUTTER_NEARBYINT (width);
height = CLUTTER_NEARBYINT (height);
/* XXX: NB the width/height may now be up to 0.5px too small so we
* must also pad by 0.25px all around to account for this. In total we
* must padd by at least 0.75px around all sides. */
/* XXX: The furthest that we can overshoot the bottom right corner by
* here is 1.75px in total if you consider that the 0.75 padding could
* just cross an integer boundary and so ceil will effectively add 1.
*/
box->x2 = ceilf (box->x2 + 0.75);
box->y2 = ceilf (box->y2 + 0.75);
/* Now we redefine the top-left relative to the bottom right based on the
* rounded width/height determined above + a constant so that the overall
* size of the box will be stable and not dependent on the box's
* position.
*
* Adding 3px to the width/height will ensure we cover the maximum of
* 1.75px padding on the bottom/right and still ensure we have > 0.75px
* padding on the top/left.
*/
box->x1 = box->x2 - width - 3;
box->y1 = box->y2 - height - 3;
}
/**
* clutter_actor_box_scale:
* @box: a #ClutterActorBox
* @scale: scale factor for resizing this box
*
* Rescale the @box by provided @scale factor.
*
* Since: 1.6
*/
void
clutter_actor_box_scale (ClutterActorBox *box,
gfloat scale)
{
g_return_if_fail (box != NULL);
box->x1 *= scale;
box->x2 *= scale;
box->y1 *= scale;
box->y2 *= scale;
}
/**
* clutter_actor_box_is_initialized:
* @box: a #ClutterActorBox
*
* Checks if @box has been initialized, a #ClutterActorBox is uninitialized
* if it has a size of -1 at an origin of 0, 0.
*
* Returns: %TRUE if the box is uninitialized, %FALSE if it isn't
*/
gboolean
clutter_actor_box_is_initialized (ClutterActorBox *box)
{
gboolean x1_uninitialized, x2_uninitialized;
gboolean y1_uninitialized, y2_uninitialized;
g_return_val_if_fail (box != NULL, TRUE);
x1_uninitialized = isinf (box->x1);
x2_uninitialized = isinf (box->x2) && signbit (box->x2);
y1_uninitialized = isinf (box->y1);
y2_uninitialized = isinf (box->y2) && signbit (box->y2);
return !x1_uninitialized || !x2_uninitialized ||
!y1_uninitialized || !y2_uninitialized;
}
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
clutter_actor_box_copy,
clutter_actor_box_free,

View File

@ -51,7 +51,7 @@
struct _ClutterActorMetaPrivate
{
ClutterActor *actor;
gulong destroy_id;
guint destroy_id;
gchar *name;
@ -81,49 +81,28 @@ static void
on_actor_destroy (ClutterActor *actor,
ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
priv->actor = NULL;
meta->priv->actor = NULL;
}
static void
clutter_actor_meta_real_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
g_warn_if_fail (!priv->actor ||
!CLUTTER_ACTOR_IN_PAINT (priv->actor));
g_warn_if_fail (!actor || !CLUTTER_ACTOR_IN_PAINT (actor));
if (priv->actor == actor)
if (meta->priv->actor == actor)
return;
g_clear_signal_handler (&priv->destroy_id, priv->actor);
if (meta->priv->destroy_id != 0)
{
g_signal_handler_disconnect (meta->priv->actor, meta->priv->destroy_id);
meta->priv->destroy_id = 0;
}
priv->actor = actor;
meta->priv->actor = actor;
if (priv->actor != NULL)
priv->destroy_id = g_signal_connect (priv->actor, "destroy",
G_CALLBACK (on_actor_destroy),
meta);
}
static void
clutter_actor_meta_real_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
g_warn_if_fail (!priv->actor ||
!CLUTTER_ACTOR_IN_PAINT (priv->actor));
priv->is_enabled = is_enabled;
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]);
if (meta->priv->actor != NULL)
meta->priv->destroy_id = g_signal_connect (meta->priv->actor, "destroy",
G_CALLBACK (on_actor_destroy),
meta);
}
static void
@ -156,21 +135,20 @@ clutter_actor_meta_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (CLUTTER_ACTOR_META (gobject));
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
switch (prop_id)
{
case PROP_ACTOR:
g_value_set_object (value, priv->actor);
g_value_set_object (value, meta->priv->actor);
break;
case PROP_NAME:
g_value_set_string (value, priv->name);
g_value_set_string (value, meta->priv->name);
break;
case PROP_ENABLED:
g_value_set_boolean (value, priv->is_enabled);
g_value_set_boolean (value, meta->priv->is_enabled);
break;
default:
@ -182,11 +160,10 @@ clutter_actor_meta_get_property (GObject *gobject,
static void
clutter_actor_meta_finalize (GObject *gobject)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (CLUTTER_ACTOR_META (gobject));
ClutterActorMetaPrivate *priv = CLUTTER_ACTOR_META (gobject)->priv;
if (priv->actor != NULL)
g_clear_signal_handler (&priv->destroy_id, priv->actor);
if (priv->destroy_id != 0 && priv->actor != NULL)
g_signal_handler_disconnect (priv->actor, priv->destroy_id);
g_free (priv->name);
@ -199,7 +176,6 @@ clutter_actor_meta_class_init (ClutterActorMetaClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
klass->set_actor = clutter_actor_meta_real_set_actor;
klass->set_enabled = clutter_actor_meta_real_set_enabled;
/**
* ClutterActorMeta:actor:
@ -254,11 +230,9 @@ clutter_actor_meta_class_init (ClutterActorMetaClass *klass)
void
clutter_actor_meta_init (ClutterActorMeta *self)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (self);
priv->is_enabled = TRUE;
priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT;
self->priv = clutter_actor_meta_get_instance_private (self);
self->priv->is_enabled = TRUE;
self->priv->priority = CLUTTER_ACTOR_META_PRIORITY_DEFAULT;
}
/**
@ -276,17 +250,13 @@ void
clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *name)
{
ClutterActorMetaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
priv = clutter_actor_meta_get_instance_private (meta);
if (g_strcmp0 (priv->name, name) == 0)
if (g_strcmp0 (meta->priv->name, name) == 0)
return;
g_free (priv->name);
priv->name = g_strdup (name);
g_free (meta->priv->name);
meta->priv->name = g_strdup (name);
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_NAME]);
}
@ -307,13 +277,9 @@ clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *
clutter_actor_meta_get_name (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->name;
return meta->priv->name;
}
/**
@ -329,17 +295,16 @@ void
clutter_actor_meta_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterActorMetaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
priv = clutter_actor_meta_get_instance_private (meta);
is_enabled = !!is_enabled;
if (priv->is_enabled == is_enabled)
if (meta->priv->is_enabled == is_enabled)
return;
CLUTTER_ACTOR_META_GET_CLASS (meta)->set_enabled (meta, is_enabled);
meta->priv->is_enabled = is_enabled;
g_object_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_ENABLED]);
}
/**
@ -355,13 +320,9 @@ clutter_actor_meta_set_enabled (ClutterActorMeta *meta,
gboolean
clutter_actor_meta_get_enabled (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), FALSE);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->is_enabled;
return meta->priv->is_enabled;
}
/*
@ -397,54 +358,40 @@ _clutter_actor_meta_set_actor (ClutterActorMeta *meta,
ClutterActor *
clutter_actor_meta_get_actor (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->actor;
return meta->priv->actor;
}
void
_clutter_actor_meta_set_priority (ClutterActorMeta *meta,
gint priority)
{
ClutterActorMetaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR_META (meta));
priv = clutter_actor_meta_get_instance_private (meta);
/* This property shouldn't be modified after the actor meta is in
use because ClutterMetaGroup doesn't resort the list when it
changes. If we made the priority public then we could either make
the priority a construct-only property or listen for
notifications on the property from the ClutterMetaGroup and
resort. */
g_return_if_fail (priv->actor == NULL);
g_return_if_fail (meta->priv->actor == NULL);
priv->priority = priority;
meta->priv->priority = priority;
}
gint
_clutter_actor_meta_get_priority (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), 0);
priv = clutter_actor_meta_get_instance_private (meta);
return priv->priority;
return meta->priv->priority;
}
gboolean
_clutter_actor_meta_is_internal (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
gint priority = priv->priority;
gint priority = meta->priv->priority;
return (priority <= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_LOW ||
priority >= CLUTTER_ACTOR_META_PRIORITY_INTERNAL_HIGH);
@ -491,21 +438,19 @@ void
_clutter_meta_group_add_meta (ClutterMetaGroup *group,
ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
GList *prev = NULL, *l;
if (priv->actor != NULL)
if (meta->priv->actor != NULL)
{
g_warning ("The meta of type '%s' with name '%s' is "
"already attached to actor '%s'",
G_OBJECT_TYPE_NAME (meta),
priv->name != NULL
? priv->name
meta->priv->name != NULL
? meta->priv->name
: "<unknown>",
clutter_actor_get_name (priv->actor) != NULL
? clutter_actor_get_name (priv->actor)
: G_OBJECT_TYPE_NAME (priv->actor));
clutter_actor_get_name (meta->priv->actor) != NULL
? clutter_actor_get_name (meta->priv->actor)
: G_OBJECT_TYPE_NAME (meta->priv->actor));
return;
}
@ -541,16 +486,13 @@ void
_clutter_meta_group_remove_meta (ClutterMetaGroup *group,
ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
if (priv->actor != group->actor)
if (meta->priv->actor != group->actor)
{
g_warning ("The meta of type '%s' with name '%s' is not "
"attached to the actor '%s'",
G_OBJECT_TYPE_NAME (meta),
priv->name != NULL
? priv->name
meta->priv->name != NULL
? meta->priv->name
: "<unknown>",
clutter_actor_get_name (group->actor) != NULL
? clutter_actor_get_name (group->actor)
@ -635,7 +577,8 @@ _clutter_meta_group_clear_metas (ClutterMetaGroup *group)
{
g_list_foreach (group->meta, (GFunc) _clutter_actor_meta_set_actor, NULL);
g_list_free_full (group->meta, g_object_unref);
g_list_foreach (group->meta, (GFunc) g_object_unref, NULL);
g_list_free (group->meta);
group->meta = NULL;
}
@ -693,10 +636,8 @@ _clutter_meta_group_get_meta (ClutterMetaGroup *group,
for (l = group->meta; l != NULL; l = l->next)
{
ClutterActorMeta *meta = l->data;
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
if (g_strcmp0 (priv->name, name) == 0)
if (g_strcmp0 (meta->priv->name, name) == 0)
return meta;
}
@ -716,8 +657,6 @@ _clutter_meta_group_get_meta (ClutterMetaGroup *group,
const gchar *
_clutter_actor_meta_get_debug_name (ClutterActorMeta *meta)
{
ClutterActorMetaPrivate *priv =
clutter_actor_meta_get_instance_private (meta);
return priv->name != NULL ? priv->name : G_OBJECT_TYPE_NAME (meta);
return meta->priv->name != NULL ? meta->priv->name
: G_OBJECT_TYPE_NAME (meta);
}

View File

@ -33,13 +33,31 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ())
#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ())
#define CLUTTER_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMeta))
#define CLUTTER_IS_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR_META))
#define CLUTTER_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass))
#define CLUTTER_IS_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR_META))
#define CLUTTER_ACTOR_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterActorMeta, clutter_actor_meta,
CLUTTER, ACTOR_META, GInitiallyUnowned);
typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate;
typedef struct _ClutterActorMetaClass ClutterActorMetaClass;
typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate;
/**
* ClutterActorMeta:
*
* The #ClutterActorMeta structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterActorMeta
{
/*< private >*/
GInitiallyUnowned parent_instance;
ClutterActorMetaPrivate *priv;
};
/**
* ClutterActorMetaClass:
@ -69,9 +87,6 @@ struct _ClutterActorMetaClass
void (* set_actor) (ClutterActorMeta *meta,
ClutterActor *actor);
void (* set_enabled) (ClutterActorMeta *meta,
gboolean is_enabled);
/*< private >*/
void (* _clutter_meta1) (void);
void (* _clutter_meta2) (void);
@ -79,8 +94,12 @@ struct _ClutterActorMetaClass
void (* _clutter_meta4) (void);
void (* _clutter_meta5) (void);
void (* _clutter_meta6) (void);
void (* _clutter_meta7) (void);
};
CLUTTER_EXPORT
GType clutter_actor_meta_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
void clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *name);

View File

@ -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
@ -36,8 +53,7 @@ G_BEGIN_DECLS
* Controls some options for how clutter_actor_traverse() iterates
* through the graph.
*/
typedef enum
{
typedef enum {
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST = 1L<<0,
CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST = 1L<<1
} ClutterActorTraverseFlags;
@ -58,8 +74,7 @@ typedef enum
* the continuing traversal. It may stop traversal completely, just
* skip over children for the current actor or continue as normal.
*/
typedef enum
{
typedef enum {
CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE = 1L<<0,
CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN = 1L<<1,
CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK = 1L<<2
@ -93,12 +108,35 @@ typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor
typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor,
gpointer user_data);
typedef struct _AnchorCoord AnchorCoord;
typedef struct _SizeRequest SizeRequest;
typedef struct _ClutterLayoutInfo ClutterLayoutInfo;
typedef struct _ClutterTransformInfo ClutterTransformInfo;
typedef struct _ClutterAnimationInfo ClutterAnimationInfo;
/* Internal helper struct to represent a point that can be stored in
either direct pixel coordinates or as a fraction of the actor's
size. It is used for the anchor point, scale center and rotation
centers. */
struct _AnchorCoord
{
gboolean is_fractional;
union
{
/* Used when is_fractional == TRUE */
struct
{
gdouble x;
gdouble y;
} fraction;
/* Use when is_fractional == FALSE */
ClutterVertex units;
} v;
};
struct _SizeRequest
{
guint age;
@ -123,7 +161,7 @@ struct _SizeRequest
struct _ClutterLayoutInfo
{
/* fixed position coordinates */
graphene_point_t fixed_pos;
ClutterPoint fixed_pos;
ClutterMargin margin;
@ -133,8 +171,8 @@ struct _ClutterLayoutInfo
guint x_expand : 1;
guint y_expand : 1;
graphene_size_t minimum;
graphene_size_t natural;
ClutterSize minimum;
ClutterSize natural;
};
const ClutterLayoutInfo * _clutter_actor_get_layout_info_or_defaults (ClutterActor *self);
@ -143,30 +181,39 @@ ClutterLayoutInfo * _clutter_actor_peek_layout_info
struct _ClutterTransformInfo
{
/* rotation */
/* rotation (angle and center) */
gdouble rx_angle;
AnchorCoord rx_center;
gdouble ry_angle;
AnchorCoord ry_center;
gdouble rz_angle;
AnchorCoord rz_center;
/* scaling */
gdouble scale_x;
gdouble scale_y;
gdouble scale_z;
AnchorCoord scale_center;
/* anchor point */
AnchorCoord anchor;
/* translation */
graphene_point3d_t translation;
ClutterVertex translation;
/* z_position */
gfloat z_position;
/* transformation center */
graphene_point_t pivot;
ClutterPoint 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;
};
@ -193,6 +240,9 @@ ClutterAnimationInfo * _clutter_actor_get_animation_info
ClutterTransition * _clutter_actor_create_transition (ClutterActor *self,
GParamSpec *pspec,
...);
ClutterTransition * _clutter_actor_get_transition (ClutterActor *self,
GParamSpec *pspec);
gboolean _clutter_actor_foreach_child (ClutterActor *self,
ClutterForeachCallback callback,
gpointer user_data);
@ -203,11 +253,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,
@ -225,24 +275,35 @@ void _clutter_actor_set_enable_paint_unmapped
void _clutter_actor_set_has_pointer (ClutterActor *self,
gboolean has_pointer);
void _clutter_actor_set_has_key_focus (ClutterActor *self,
gboolean has_key_focus);
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
ClutterRedrawFlags flags,
ClutterPaintVolume *clip_volume);
void _clutter_actor_queue_redraw_full (ClutterActor *self,
ClutterRedrawFlags flags,
ClutterPaintVolume *volume,
ClutterEffect *effect);
void _clutter_actor_queue_redraw_full (ClutterActor *self,
const ClutterPaintVolume *volume,
ClutterEffect *effect);
void _clutter_actor_finish_queue_redraw (ClutterActor *self);
ClutterPaintVolume * _clutter_actor_get_queue_redraw_clip (ClutterActor *self);
void _clutter_actor_set_queue_redraw_clip (ClutterActor *self,
ClutterPaintVolume *clip_volume);
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);
guint32 _clutter_actor_get_pick_id (ClutterActor *self);
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,25 +313,15 @@ 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);
float clutter_actor_get_real_resource_scale (ClutterActor *actor);
CoglFramebuffer * _clutter_actor_get_active_framebuffer (ClutterActor *actor);
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
CoglTexture *texture);
void clutter_actor_finish_layout (ClutterActor *self,
int phase);
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
gboolean clutter_actor_is_painting_unmapped (ClutterActor *self);
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

View File

@ -39,8 +39,6 @@
#include <clutter/clutter-types.h>
#include <clutter/clutter-event.h>
#include <clutter/clutter-paint-context.h>
#include <clutter/clutter-pick-context.h>
G_BEGIN_DECLS
@ -142,6 +140,11 @@ struct _ClutterActor
* ClutterActorClass:
* @show: signal class handler for #ClutterActor::show; it must chain
* up to the parent's implementation
* @show_all: virtual function for containers and composite actors, to
* determine which children should be shown when calling
* clutter_actor_show_all() on the actor. Defaults to calling
* clutter_actor_show(). This virtual function is deprecated and it
* should not be overridden.
* @hide: signal class handler for #ClutterActor::hide; it must chain
* up to the parent's implementation
* @hide_all: virtual function for containers and composite actors, to
@ -170,23 +173,18 @@ struct _ClutterActor
* @get_preferred_height: virtual function, used when querying the minimum
* and natural heights of an actor for a given width; it is used by
* clutter_actor_get_preferred_height()
* @allocate: virtual function, used when setting the coordinates of an
* actor; it is used by clutter_actor_allocate(); when overriding this
* function without chaining up, clutter_actor_set_allocation() must be
* called and children must be allocated by the implementation, when
* chaining up though, those things will be done by the parent's
* implementation.
* @allocate: virtual function, used when settings the coordinates of an
* actor; it is used by clutter_actor_allocate(); it must chain up to
* the parent's implementation, or call clutter_actor_set_allocation()
* @apply_transform: virtual function, used when applying the transformations
* to an actor before painting it or when transforming coordinates or
* the allocation; if the transformation calculated by this function may
* have changed, the cached transformation must be invalidated by calling
* clutter_actor_invalidate_transform(); it must chain up to the parent's
* implementation
* the allocation; it must chain up to the parent's implementation
* @parent_set: signal class handler for the #ClutterActor::parent-set
* @destroy: signal class handler for #ClutterActor::destroy. It must
* chain up to the parent's implementation
* @pick: virtual function, used to draw an outline of the actor with
* the given color
* @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
@ -223,20 +221,23 @@ struct _ClutterActorClass
/*< public >*/
void (* show) (ClutterActor *self);
void (* show_all) (ClutterActor *self);
void (* hide) (ClutterActor *self);
void (* hide_all) (ClutterActor *self);
void (* realize) (ClutterActor *self);
void (* unrealize) (ClutterActor *self);
void (* map) (ClutterActor *self);
void (* unmap) (ClutterActor *self);
void (* paint) (ClutterActor *self,
ClutterPaintContext *paint_context);
void (* paint) (ClutterActor *self);
void (* parent_set) (ClutterActor *actor,
ClutterActor *old_parent);
void (* destroy) (ClutterActor *self);
void (* pick) (ClutterActor *actor,
ClutterPickContext *pick_context);
const ClutterColor *color);
void (* queue_redraw) (ClutterActor *actor,
ClutterActor *leaf_that_queued);
/* size negotiation */
void (* get_preferred_width) (ClutterActor *self,
@ -248,11 +249,12 @@ struct _ClutterActorClass
gfloat *min_height_p,
gfloat *natural_height_p);
void (* allocate) (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
/* transformations */
void (* apply_transform) (ClutterActor *actor,
graphene_matrix_t *matrix);
ClutterMatrix *matrix);
/* event signals */
gboolean (* event) (ClutterActor *actor,
@ -293,14 +295,10 @@ struct _ClutterActorClass
gboolean (* touch_event) (ClutterActor *self,
ClutterTouchEvent *event);
gboolean (* has_accessible) (ClutterActor *self);
void (* resource_scale_changed) (ClutterActor *self);
float (* calculate_resource_scale) (ClutterActor *self,
int phase);
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[25];
gpointer _padding_dummy[26];
};
/**
@ -351,17 +349,9 @@ void clutter_actor_map
CLUTTER_EXPORT
void clutter_actor_unmap (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_paint (ClutterActor *self,
ClutterPaintContext *paint_context);
void clutter_actor_paint (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_continue_paint (ClutterActor *self,
ClutterPaintContext *paint_context);
CLUTTER_EXPORT
void clutter_actor_pick (ClutterActor *actor,
ClutterPickContext *pick_context);
CLUTTER_EXPORT
void clutter_actor_continue_pick (ClutterActor *actor,
ClutterPickContext *pick_context);
void clutter_actor_continue_paint (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_queue_redraw (ClutterActor *self);
CLUTTER_EXPORT
@ -378,8 +368,6 @@ CLUTTER_EXPORT
const gchar * clutter_actor_get_name (ClutterActor *self);
CLUTTER_EXPORT
AtkObject * clutter_actor_get_accessible (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_has_accessible (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_is_visible (ClutterActor *self);
@ -412,31 +400,38 @@ void clutter_actor_get_preferred_size
gfloat *natural_height_p);
CLUTTER_EXPORT
void clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_preferred_size (ClutterActor *self,
float x,
float y);
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_available_size (ClutterActor *self,
gfloat x,
gfloat y,
gfloat available_width,
gfloat available_height);
gfloat available_height,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_align_fill (ClutterActor *self,
const ClutterActorBox *box,
gdouble x_align,
gdouble y_align,
gboolean x_fill,
gboolean y_fill);
gboolean y_fill,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_set_allocation (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_get_allocation_box (ClutterActor *self,
ClutterActorBox *box);
CLUTTER_EXPORT
void clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
ClutterVertex verts[]);
CLUTTER_EXPORT
gboolean clutter_actor_has_allocation (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_set_size (ClutterActor *self,
@ -451,10 +446,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,17 +577,12 @@ 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
gboolean clutter_actor_get_paint_box (ClutterActor *self,
ClutterActorBox *box);
CLUTTER_EXPORT
float clutter_actor_get_resource_scale (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_has_overlaps (ClutterActor *self);
@ -799,21 +785,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,
@ -830,16 +811,16 @@ gboolean clutter_actor_transform_stage_point
gfloat *y_out);
CLUTTER_EXPORT
void clutter_actor_get_abs_allocation_vertices (ClutterActor *self,
graphene_point3d_t *verts);
ClutterVertex verts[]);
CLUTTER_EXPORT
void clutter_actor_apply_transform_to_point (ClutterActor *self,
const graphene_point3d_t *point,
graphene_point3d_t *vertex);
const ClutterVertex *point,
ClutterVertex *vertex);
CLUTTER_EXPORT
void clutter_actor_apply_relative_transform_to_point (ClutterActor *self,
ClutterActor *ancestor,
const graphene_point3d_t *point,
graphene_point3d_t *vertex);
const ClutterVertex *point,
ClutterVertex *vertex);
/* Implicit animations */
CLUTTER_EXPORT
@ -883,11 +864,6 @@ void clutter_actor_set_opacity_override
CLUTTER_EXPORT
gint clutter_actor_get_opacity_override (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_inhibit_culling (ClutterActor *actor);
CLUTTER_EXPORT
void clutter_actor_uninhibit_culling (ClutterActor *actor);
/**
* ClutterActorCreateChildFunc:
* @item: (type GObject): the item in the model
@ -920,20 +896,6 @@ void clutter_actor_bind_model_with_properties
const char *first_model_property,
...);
CLUTTER_EXPORT
void clutter_actor_pick_box (ClutterActor *self,
ClutterPickContext *pick_context,
const ClutterActorBox *box);
CLUTTER_EXPORT
GList * clutter_actor_peek_stage_views (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_invalidate_transform (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_invalidate_paint_volume (ClutterActor *self);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_H__ */

View File

@ -58,7 +58,6 @@ struct _ClutterAlignConstraint
ClutterActor *actor;
ClutterActor *source;
ClutterAlignAxis align_axis;
graphene_point_t pivot;
gfloat factor;
};
@ -73,7 +72,6 @@ enum
PROP_SOURCE,
PROP_ALIGN_AXIS,
PROP_PIVOT_POINT,
PROP_FACTOR,
PROP_LAST
@ -86,11 +84,13 @@ G_DEFINE_TYPE (ClutterAlignConstraint,
CLUTTER_TYPE_CONSTRAINT);
static void
source_queue_relayout (ClutterActor *actor,
ClutterAlignConstraint *align)
source_position_changed (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
ClutterAlignConstraint *align)
{
if (align->actor != NULL)
_clutter_actor_queue_only_relayout (align->actor);
clutter_actor_queue_relayout (align->actor);
}
static void
@ -135,41 +135,35 @@ clutter_align_constraint_update_allocation (ClutterConstraint *constraint,
ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
gfloat offset_x_start, offset_y_start;
gfloat pivot_x, pivot_y;
gfloat source_x, source_y;
if (align->source == NULL)
return;
clutter_actor_box_get_size (allocation, &actor_width, &actor_height);
clutter_actor_get_position (align->source, &source_x, &source_y);
clutter_actor_get_size (align->source, &source_width, &source_height);
pivot_x = align->pivot.x == -1.f
? align->factor
: align->pivot.x;
pivot_y = align->pivot.y == -1.f
? align->factor
: align->pivot.y;
offset_x_start = pivot_x * -actor_width;
offset_y_start = pivot_y * -actor_height;
switch (align->align_axis)
{
case CLUTTER_ALIGN_X_AXIS:
allocation->x1 += offset_x_start + (source_width * align->factor);
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->x2 = allocation->x1 + actor_width;
break;
case CLUTTER_ALIGN_Y_AXIS:
allocation->y1 += offset_y_start + (source_height * align->factor);
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->y2 = allocation->y1 + actor_height;
break;
case CLUTTER_ALIGN_BOTH:
allocation->x1 += offset_x_start + (source_width * align->factor);
allocation->y1 += offset_y_start + (source_height * align->factor);
allocation->x1 = ((source_width - actor_width) * align->factor)
+ source_x;
allocation->y1 = ((source_height - actor_height) * align->factor)
+ source_y;
allocation->x2 = allocation->x1 + actor_width;
allocation->y2 = allocation->y1 + actor_height;
break;
@ -193,7 +187,7 @@ clutter_align_constraint_dispose (GObject *gobject)
G_CALLBACK (source_destroyed),
align);
g_signal_handlers_disconnect_by_func (align->source,
G_CALLBACK (source_queue_relayout),
G_CALLBACK (source_position_changed),
align);
align->source = NULL;
}
@ -219,10 +213,6 @@ clutter_align_constraint_set_property (GObject *gobject,
clutter_align_constraint_set_align_axis (align, g_value_get_enum (value));
break;
case PROP_PIVOT_POINT:
clutter_align_constraint_set_pivot_point (align, g_value_get_boxed (value));
break;
case PROP_FACTOR:
clutter_align_constraint_set_factor (align, g_value_get_float (value));
break;
@ -251,16 +241,6 @@ clutter_align_constraint_get_property (GObject *gobject,
g_value_set_enum (value, align->align_axis);
break;
case PROP_PIVOT_POINT:
{
graphene_point_t point;
clutter_align_constraint_get_pivot_point (align, &point);
g_value_set_boxed (value, &point);
}
break;
case PROP_FACTOR:
g_value_set_float (value, align->factor);
break;
@ -314,30 +294,6 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass)
CLUTTER_ALIGN_X_AXIS,
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT);
/**
* ClutterAlignConstraint:pivot-point:
*
* The pivot point used by the constraint. The pivot point is the
* point in the constraint actor around which the aligning is applied,
* with (0, 0) being the top left corner of the actor and (1, 1) the
* bottom right corner of the actor.
*
* For example, setting the pivot point to (0.5, 0.5) and using a factor
* of 1 for both axes will align the actors horizontal and vertical
* center point with the bottom right corner of the source actor.
*
* By default, the pivot point is set to (-1, -1), which means it's not
* used and the constrained actor will be aligned to always stay inside
* the source actor.
*/
obj_props[PROP_PIVOT_POINT] =
g_param_spec_boxed ("pivot-point",
P_("Pivot point"),
P_("The pivot point"),
GRAPHENE_TYPE_POINT,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
/**
* ClutterAlignConstraint:factor:
*
@ -370,8 +326,6 @@ clutter_align_constraint_init (ClutterAlignConstraint *self)
self->actor = NULL;
self->source = NULL;
self->align_axis = CLUTTER_ALIGN_X_AXIS;
self->pivot.x = -1.f;
self->pivot.y = -1.f;
self->factor = 0.0f;
}
@ -449,15 +403,15 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
G_CALLBACK (source_destroyed),
align);
g_signal_handlers_disconnect_by_func (old_source,
G_CALLBACK (source_queue_relayout),
G_CALLBACK (source_position_changed),
align);
}
align->source = source;
if (align->source != NULL)
{
g_signal_connect (align->source, "queue-relayout",
G_CALLBACK (source_queue_relayout),
g_signal_connect (align->source, "allocation-changed",
G_CALLBACK (source_position_changed),
align);
g_signal_connect (align->source, "destroy",
G_CALLBACK (source_destroyed),
@ -534,60 +488,6 @@ clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align)
return align->align_axis;
}
/**
* clutter_align_constraint_set_pivot_point:
* @align: a #ClutterAlignConstraint
* @pivot_point: A #GraphenePoint
*
* Sets the pivot point used by the constraint, the pivot point is the
* point in the constraint actor around which the aligning is applied,
* with (0, 0) being the top left corner of the actor and (1, 1) the
* bottom right corner of the actor.
*
* If -1 is used, the pivot point is unset and the constrained actor
* will be aligned to always stay inside the source actor.
*/
void
clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
const graphene_point_t *pivot_point)
{
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
g_return_if_fail (pivot_point != NULL);
g_return_if_fail (pivot_point->x == -1.f ||
(pivot_point->x >= 0.f && pivot_point->x <= 1.f));
g_return_if_fail (pivot_point->y == -1.f ||
(pivot_point->y >= 0.f && pivot_point->y <= 1.f));
if (graphene_point_equal (&align->pivot, pivot_point))
return;
align->pivot = *pivot_point;
if (align->actor != NULL)
clutter_actor_queue_relayout (align->actor);
g_object_notify_by_pspec (G_OBJECT (align), obj_props[PROP_PIVOT_POINT]);
}
/**
* clutter_align_constraint_get_pivot_point
* @align: a #ClutterAlignConstraint
* @pivot_point: (out caller-allocates): return location for a #GraphenePoint
*
* Gets the pivot point used by the constraint set with
* clutter_align_constraint_set_pivot_point(). If no custom pivot
* point is set, -1 is set.
*/
void
clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
graphene_point_t *pivot_point)
{
g_return_if_fail (CLUTTER_IS_ALIGN_CONSTRAINT (align));
g_return_if_fail (pivot_point != NULL);
*pivot_point = align->pivot;
}
/**
* clutter_align_constraint_set_factor:
* @align: a #ClutterAlignConstraint

View File

@ -67,12 +67,6 @@ void clutter_align_constraint_set_align_axis (ClutterAlignConstrai
CLUTTER_EXPORT
ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align);
CLUTTER_EXPORT
void clutter_align_constraint_set_pivot_point (ClutterAlignConstraint *align,
const graphene_point_t *pivot_point);
CLUTTER_EXPORT
void clutter_align_constraint_get_pivot_point (ClutterAlignConstraint *align,
graphene_point_t *pivot_point);
CLUTTER_EXPORT
void clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
gfloat factor);
CLUTTER_EXPORT

View File

@ -27,23 +27,37 @@
* @short_description: Interface for animatable classes
*
* #ClutterAnimatable is an interface that allows a #GObject class
* to control how an actor will animate a property.
* to control how a #ClutterAnimation will animate a property.
*
* Each #ClutterAnimatable should implement the
* #ClutterAnimatableInterface.interpolate_property() virtual function of the
* #ClutterAnimatableIface.interpolate_property() virtual function of the
* interface to compute the animation state between two values of an interval
* depending on a progress factor, expressed as a floating point value.
*
* If a #ClutterAnimatable is animated by a #ClutterAnimation
* instance, the #ClutterAnimation will call
* clutter_animatable_interpolate_property() passing the name of the
* currently animated property; the values interval; and the progress factor.
* The #ClutterAnimatable implementation should return the computed value for
* the animated
* property.
*
* #ClutterAnimatable is available since Clutter 1.0
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-animatable.h"
#include "clutter-interval.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "deprecated/clutter-animatable.h"
#include "deprecated/clutter-animation.h"
typedef ClutterAnimatableIface ClutterAnimatableInterface;
G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
static void
@ -51,6 +65,80 @@ clutter_animatable_default_init (ClutterAnimatableInterface *iface)
{
}
/**
* clutter_animatable_animate_property:
* @animatable: a #ClutterAnimatable
* @animation: a #ClutterAnimation
* @property_name: the name of the animated property
* @initial_value: the initial value of the animation interval
* @final_value: the final value of the animation interval
* @progress: the progress factor
* @value: return location for the animation value
*
* Calls the animate_property() virtual function for @animatable.
*
* The @initial_value and @final_value #GValue<!-- -->s must contain
* the same type; @value must have been initialized to the same
* type of @initial_value and @final_value.
*
* All implementation of the #ClutterAnimatable interface must
* implement this function.
*
* Return value: %TRUE if the value has been validated and can
* be applied to the #ClutterAnimatable, and %FALSE otherwise
*
* Since: 1.0
*
* Deprecated: 1.8: Use clutter_animatable_interpolate_value()
* instead
*/
gboolean
clutter_animatable_animate_property (ClutterAnimatable *animatable,
ClutterAnimation *animation,
const gchar *property_name,
const GValue *initial_value,
const GValue *final_value,
gdouble progress,
GValue *value)
{
ClutterAnimatableIface *iface;
gboolean res;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
g_return_val_if_fail (property_name != NULL, FALSE);
g_return_val_if_fail (initial_value != NULL && final_value != NULL, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (initial_value) != G_TYPE_INVALID, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (final_value) != G_TYPE_INVALID, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
g_return_val_if_fail (G_VALUE_TYPE (value) == G_VALUE_TYPE (initial_value) &&
G_VALUE_TYPE (value) == G_VALUE_TYPE (final_value),
FALSE);
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
if (iface->animate_property == NULL)
{
ClutterInterval *interval;
interval = clutter_animation_get_interval (animation, property_name);
if (interval == NULL)
return FALSE;
res = clutter_animatable_interpolate_value (animatable, property_name,
interval,
progress,
value);
}
else
res = iface->animate_property (animatable, animation,
property_name,
initial_value, final_value,
progress,
value);
return res;
}
/**
* clutter_animatable_find_property:
* @animatable: a #ClutterAnimatable
@ -67,7 +155,7 @@ GParamSpec *
clutter_animatable_find_property (ClutterAnimatable *animatable,
const gchar *property_name)
{
ClutterAnimatableInterface *iface;
ClutterAnimatableIface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
g_return_val_if_fail (property_name != NULL, NULL);
@ -97,7 +185,7 @@ clutter_animatable_get_initial_state (ClutterAnimatable *animatable,
const gchar *property_name,
GValue *value)
{
ClutterAnimatableInterface *iface;
ClutterAnimatableIface *iface;
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
g_return_if_fail (property_name != NULL);
@ -126,7 +214,7 @@ clutter_animatable_set_final_state (ClutterAnimatable *animatable,
const gchar *property_name,
const GValue *value)
{
ClutterAnimatableInterface *iface;
ClutterAnimatableIface *iface;
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
g_return_if_fail (property_name != NULL);
@ -172,7 +260,7 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
gdouble progress,
GValue *value)
{
ClutterAnimatableInterface *iface;
ClutterAnimatableIface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
g_return_val_if_fail (property_name != NULL, FALSE);
@ -194,25 +282,3 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
else
return clutter_interval_compute_value (interval, progress, value);
}
/**
* clutter_animatable_get_actor:
* @animatable: a #ClutterAnimatable
*
* Get animated actor.
*
* Return value: (transfer none): a #ClutterActor
*/
ClutterActor *
clutter_animatable_get_actor (ClutterAnimatable *animatable)
{
ClutterAnimatableInterface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
g_return_val_if_fail (iface->get_actor, NULL);
return iface->get_actor (animatable);
}

View File

@ -33,15 +33,26 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ())
#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ())
#define CLUTTER_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatable))
#define CLUTTER_IS_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATABLE))
#define CLUTTER_ANIMATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatableIface))
CLUTTER_EXPORT
G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
CLUTTER, ANIMATABLE,
GObject)
typedef struct _ClutterAnimatableIface ClutterAnimatableIface;
/**
* ClutterAnimatableInterface:
* ClutterAnimatable:
*
* #ClutterAnimatable is an opaque structure whose members cannot be directly
* accessed
*
* Since: 1.0
*/
/**
* ClutterAnimatableIface:
* @animate_property: virtual function for custom interpolation of a
* property. This virtual function is deprecated
* @find_property: virtual function for retrieving the #GParamSpec of
* an animatable property
* @get_initial_state: virtual function for retrieving the initial
@ -50,16 +61,25 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
* animatable property
* @interpolate_value: virtual function for interpolating the progress
* of a property
* @get_actor: virtual function for getting associated actor
*
* Base interface for #GObject<!-- -->s that can be animated by a
* a #ClutterAnimation.
*
* Since: 1.0
*/
struct _ClutterAnimatableInterface
struct _ClutterAnimatableIface
{
/*< private >*/
GTypeInterface parent_iface;
/*< public >*/
gboolean (* animate_property) (ClutterAnimatable *animatable,
ClutterAnimation *animation,
const gchar *property_name,
const GValue *initial_value,
const GValue *final_value,
gdouble progress,
GValue *value);
GParamSpec *(* find_property) (ClutterAnimatable *animatable,
const gchar *property_name);
void (* get_initial_state) (ClutterAnimatable *animatable,
@ -73,9 +93,11 @@ struct _ClutterAnimatableInterface
ClutterInterval *interval,
gdouble progress,
GValue *value);
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
};
CLUTTER_EXPORT
GType clutter_animatable_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
GParamSpec *clutter_animatable_find_property (ClutterAnimatable *animatable,
const gchar *property_name);
@ -94,9 +116,6 @@ gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
gdouble progress,
GValue *value);
CLUTTER_EXPORT
ClutterActor * clutter_animatable_get_actor (ClutterAnimatable *animatable);
G_END_DECLS
#endif /* __CLUTTER_ANIMATABLE_H__ */

View File

@ -30,8 +30,11 @@
#ifndef __GI_SCANNER__
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActor, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAlignConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAnimatable, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindingPool, g_object_unref)
@ -41,15 +44,21 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBoxLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBrightnessContrastEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterCanvas, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterChildMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClickAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClone, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColorizeEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContent, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeformEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDesaturateEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeviceManager, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDragAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDropAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFixedLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFlowLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGestureAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGridLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterImage, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInputDevice, g_object_unref)
@ -83,10 +92,14 @@ 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 (ClutterPaintContext, clutter_paint_context_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterMatrix, clutter_matrix_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintNode, clutter_paint_node_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPaintVolume, clutter_paint_volume_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPathNode, clutter_path_node_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPoint, clutter_point_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterRect, clutter_rect_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterSize, clutter_size_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterVertex, clutter_vertex_free)
#endif /* __GI_SCANNER__ */

View File

@ -23,9 +23,11 @@
#define __CLUTTER_BACKEND_PRIVATE_H__
#include <clutter/clutter-backend.h>
#include <clutter/clutter-seat.h>
#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-stage-window.h>
#include "clutter-event-translator.h"
#define CLUTTER_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND, ClutterBackendClass))
#define CLUTTER_IS_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND))
#define CLUTTER_BACKEND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND, ClutterBackendClass))
@ -46,6 +48,8 @@ struct _ClutterBackend
CoglOnscreen *dummy_onscreen;
ClutterDeviceManager *device_manager;
cairo_font_options_t *font_options;
gchar *font_name;
@ -53,9 +57,7 @@ struct _ClutterBackend
gfloat units_per_em;
gint32 units_serial;
float fallback_resource_scale;
ClutterStageWindow *stage_window;
GList *event_translators;
ClutterInputMethod *input_method;
};
@ -73,6 +75,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);
@ -85,14 +88,21 @@ struct _ClutterBackendClass
GError **error);
gboolean (* create_context) (ClutterBackend *backend,
GError **error);
ClutterDeviceManager *(* get_device_manager) (ClutterBackend *backend);
void (* copy_event_data) (ClutterBackend *backend,
const ClutterEvent *src,
ClutterEvent *dest);
void (* free_event_data) (ClutterBackend *backend,
ClutterEvent *event);
gboolean (* translate_event) (ClutterBackend *backend,
gpointer native,
ClutterEvent *event);
ClutterSeat * (* get_default_seat) (ClutterBackend *backend);
PangoDirection (* get_keymap_direction) (ClutterBackend *backend);
gboolean (* is_display_server) (ClutterBackend *backend);
void (* bell_notify) (ClutterBackend *backend);
/* signals */
void (* resolution_changed) (ClutterBackend *backend);
@ -115,32 +125,37 @@ gboolean _clutter_backend_pre_parse (Clutter
gboolean _clutter_backend_post_parse (ClutterBackend *backend,
GError **error);
CLUTTER_EXPORT
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);
gboolean _clutter_backend_translate_event (ClutterBackend *backend,
gpointer native,
ClutterEvent *event);
CLUTTER_EXPORT
void _clutter_backend_add_event_translator (ClutterBackend *backend,
ClutterEventTranslator *translator);
void _clutter_backend_remove_event_translator (ClutterBackend *backend,
ClutterEventTranslator *translator);
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend,
PangoFontDescription *font_desc);
gint32 _clutter_backend_get_units_serial (ClutterBackend *backend);
PangoDirection _clutter_backend_get_keymap_direction (ClutterBackend *backend);
CLUTTER_EXPORT
void _clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend);
void clutter_set_allowed_drivers (const char *drivers);
CLUTTER_EXPORT
ClutterStageWindow * clutter_backend_get_stage_window (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
float fallback_resource_scale);
float clutter_backend_get_fallback_resource_scale (ClutterBackend *backend);
gboolean clutter_backend_is_display_server (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_destroy (ClutterBackend *backend);
void clutter_try_set_windowing_backend (const char *drivers);
G_END_DECLS

View File

@ -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"
@ -49,9 +51,33 @@
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
#include "clutter-stage-window.h"
#include "clutter-device-manager-private.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-backend.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_INPUT_EVDEV
#include "evdev/clutter-device-manager-evdev.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 +93,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,22 +107,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);
if (backend->stage_window)
{
g_object_remove_weak_pointer (G_OBJECT (backend->stage_window),
(gpointer *) &backend->stage_window);
backend->stage_window = NULL;
}
/* remove all event translators */
g_clear_pointer (&backend->event_translators, g_list_free);
g_clear_pointer (&backend->cogl_source, g_source_destroy);
g_clear_pointer (&backend->font_name, g_free);
g_clear_pointer (&backend->font_options, cairo_font_options_destroy);
g_clear_object (&backend->input_method);
g_clear_pointer (&backend->dummy_onscreen, cogl_object_unref);
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)->finalize (gobject);
}
static gfloat
get_units_per_em (ClutterBackend *backend,
PangoFontDescription *font_desc)
@ -189,20 +227,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 +254,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 +270,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 +284,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;
@ -355,7 +400,7 @@ clutter_backend_real_create_context (ClutterBackend *backend,
else
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to initialize the Clutter backend: no available drivers found.");
_("Unable to initialize the Clutter backend: no available drivers found."));
return FALSE;
}
@ -382,6 +427,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_SYNC_TO_VBLANK;
}
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 +444,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 +470,148 @@ 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)
{
const char *input_backend = NULL;
input_backend = g_getenv ("CLUTTER_INPUT_BACKEND");
if (input_backend != NULL)
input_backend = g_intern_string (input_backend);
#ifdef CLUTTER_INPUT_X11
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11) &&
(input_backend == NULL || input_backend == I_(CLUTTER_INPUT_X11)))
{
_clutter_backend_x11_events_init (backend);
}
else
#endif
#ifdef CLUTTER_INPUT_EVDEV
/* Evdev can be used regardless of the windowing system */
if ((input_backend != NULL && strcmp (input_backend, CLUTTER_INPUT_EVDEV) == 0)
#ifdef CLUTTER_WINDOWING_EGL
/* but we do want to always use it for EGL native */
|| clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL)
#endif
)
{
_clutter_events_evdev_init (backend);
}
else
#endif
if (input_backend != NULL)
{
if (input_backend != I_(CLUTTER_INPUT_NULL))
g_error ("Unrecognized input backend '%s'", input_backend);
}
else
g_error ("Unknown input backend");
}
static ClutterDeviceManager *
clutter_backend_real_get_device_manager (ClutterBackend *backend)
{
if (G_UNLIKELY (backend->device_manager == NULL))
{
g_critical ("No device manager available, expect broken input");
return NULL;
}
return backend->device_manager;
}
static gboolean
clutter_backend_real_translate_event (ClutterBackend *backend,
gpointer native,
ClutterEvent *event)
{
GList *l;
for (l = backend->event_translators;
l != NULL;
l = l->next)
{
ClutterEventTranslator *translator = l->data;
ClutterTranslateReturn retval;
retval = _clutter_event_translator_translate_event (translator,
native,
event);
if (retval == CLUTTER_TRANSLATE_QUEUE)
return TRUE;
if (retval == CLUTTER_TRANSLATE_REMOVE)
return FALSE;
}
return FALSE;
}
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:
@ -434,7 +627,8 @@ clutter_backend_class_init (ClutterBackendClass *klass)
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBackendClass, resolution_changed),
NULL, NULL, NULL,
NULL, NULL,
_clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
@ -451,7 +645,8 @@ clutter_backend_class_init (ClutterBackendClass *klass)
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBackendClass, font_changed),
NULL, NULL, NULL,
NULL, NULL,
_clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
@ -468,12 +663,16 @@ clutter_backend_class_init (ClutterBackendClass *klass)
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterBackendClass, settings_changed),
NULL, NULL, NULL,
NULL, NULL,
_clutter_marshal_VOID__VOID,
G_TYPE_NONE, 0);
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->get_device_manager = clutter_backend_real_get_device_manager;
klass->translate_event = clutter_backend_real_translate_event;
klass->create_context = clutter_backend_real_create_context;
klass->get_features = clutter_backend_real_get_features;
}
@ -484,9 +683,7 @@ clutter_backend_init (ClutterBackend *self)
self->units_per_em = -1.0;
self->units_serial = 1;
self->dummy_onscreen = NULL;
self->fallback_resource_scale = 1.f;
self->dummy_onscreen = COGL_INVALID_HANDLE;
}
void
@ -554,10 +751,6 @@ _clutter_backend_create_stage (ClutterBackend *backend,
g_assert (CLUTTER_IS_STAGE_WINDOW (stage_window));
backend->stage_window = stage_window;
g_object_add_weak_pointer (G_OBJECT (backend->stage_window),
(gpointer *) &backend->stage_window);
return stage_window;
}
@ -612,6 +805,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 +830,44 @@ _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)
{
ClutterEventExtenderInterface *iface;
ClutterBackendClass *klass;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (CLUTTER_IS_EVENT_EXTENDER (backend->device_manager))
{
iface = CLUTTER_EVENT_EXTENDER_GET_IFACE (backend->device_manager);
iface->copy_event_data (CLUTTER_EVENT_EXTENDER (backend->device_manager),
src, dest);
}
else if (klass->copy_event_data != NULL)
klass->copy_event_data (backend, src, dest);
}
void
_clutter_backend_free_event_data (ClutterBackend *backend,
ClutterEvent *event)
{
ClutterEventExtenderInterface *iface;
ClutterBackendClass *klass;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (CLUTTER_IS_EVENT_EXTENDER (backend->device_manager))
{
iface = CLUTTER_EVENT_EXTENDER_GET_IFACE (backend->device_manager);
iface->free_event_data (CLUTTER_EVENT_EXTENDER (backend->device_manager),
event);
}
else if (klass->free_event_data != NULL)
klass->free_event_data (backend, event);
}
/**
* clutter_get_default_backend:
*
@ -648,6 +890,129 @@ clutter_get_default_backend (void)
return clutter_context->backend;
}
/**
* clutter_backend_set_double_click_time:
* @backend: a #ClutterBackend
* @msec: milliseconds between two button press events
*
* Sets the maximum time between two button press events, used to
* verify whether it's a double click event or not.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-time instead
*/
void
clutter_backend_set_double_click_time (ClutterBackend *backend,
guint msec)
{
ClutterSettings *settings = clutter_settings_get_default ();
g_object_set (settings, "double-click-time", msec, NULL);
}
/**
* clutter_backend_get_double_click_time:
* @backend: a #ClutterBackend
*
* Gets the maximum time between two button press events, as set
* by clutter_backend_set_double_click_time().
*
* Return value: a time in milliseconds
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-time instead
*/
guint
clutter_backend_get_double_click_time (ClutterBackend *backend)
{
ClutterSettings *settings = clutter_settings_get_default ();
gint retval;
g_object_get (settings, "double-click-time", &retval, NULL);
return retval;
}
/**
* clutter_backend_set_double_click_distance:
* @backend: a #ClutterBackend
* @distance: a distance, in pixels
*
* Sets the maximum distance used to verify a double click event.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-distance instead
*/
void
clutter_backend_set_double_click_distance (ClutterBackend *backend,
guint distance)
{
ClutterSettings *settings = clutter_settings_get_default ();
g_object_set (settings, "double-click-distance", distance, NULL);
}
/**
* clutter_backend_get_double_click_distance:
* @backend: a #ClutterBackend
*
* Retrieves the distance used to verify a double click event
*
* Return value: a distance, in pixels.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-distance instead
*/
guint
clutter_backend_get_double_click_distance (ClutterBackend *backend)
{
ClutterSettings *settings = clutter_settings_get_default ();
gint retval;
g_object_get (settings, "double-click-distance", &retval, NULL);
return retval;
}
/**
* clutter_backend_set_resolution:
* @backend: a #ClutterBackend
* @dpi: the resolution in "dots per inch" (Physical inches aren't
* actually involved; the terminology is conventional).
*
* Sets the resolution for font handling on the screen. This is a
* scale factor between points specified in a #PangoFontDescription
* and cairo units. The default value is 96, meaning that a 10 point
* font will be 13 units high. (10 * 96. / 72. = 13.3).
*
* Applications should never need to call this function.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:font-dpi instead
*/
void
clutter_backend_set_resolution (ClutterBackend *backend,
gdouble dpi)
{
ClutterSettings *settings;
gint resolution;
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
if (dpi < 0)
resolution = -1;
else
resolution = dpi * 1024;
settings = clutter_settings_get_default ();
g_object_set (settings, "font-dpi", resolution, NULL);
}
/**
* clutter_backend_get_resolution:
* @backend: a #ClutterBackend
@ -753,6 +1118,61 @@ clutter_backend_get_font_options (ClutterBackend *backend)
return backend->font_options;
}
/**
* clutter_backend_set_font_name:
* @backend: a #ClutterBackend
* @font_name: the name of the font
*
* Sets the default font to be used by Clutter. The @font_name string
* must either be %NULL, which means that the font name from the
* default #ClutterBackend will be used; or be something that can
* be parsed by the pango_font_description_from_string() function.
*
* Since: 1.0
*
* Deprecated: 1.4: Use #ClutterSettings:font-name instead
*/
void
clutter_backend_set_font_name (ClutterBackend *backend,
const gchar *font_name)
{
ClutterSettings *settings = clutter_settings_get_default ();
g_object_set (settings, "font-name", font_name, NULL);
}
/**
* clutter_backend_get_font_name:
* @backend: a #ClutterBackend
*
* Retrieves the default font name as set by
* clutter_backend_set_font_name().
*
* Return value: the font name for the backend. The returned string is
* owned by the #ClutterBackend and should never be modified or freed
*
* Since: 1.0
*
* Deprecated: 1.4: Use #ClutterSettings:font-name instead
*/
const gchar *
clutter_backend_get_font_name (ClutterBackend *backend)
{
ClutterSettings *settings;
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
settings = clutter_settings_get_default ();
/* XXX yuck. but we return a const pointer, so we need to
* store it in the backend
*/
g_free (backend->font_name);
g_object_get (settings, "font-name", &backend->font_name, NULL);
return backend->font_name;
}
gint32
_clutter_backend_get_units_serial (ClutterBackend *backend)
{
@ -769,6 +1189,28 @@ _clutter_backend_translate_event (ClutterBackend *backend,
event);
}
void
_clutter_backend_add_event_translator (ClutterBackend *backend,
ClutterEventTranslator *translator)
{
if (g_list_find (backend->event_translators, translator) != NULL)
return;
backend->event_translators =
g_list_prepend (backend->event_translators, translator);
}
void
_clutter_backend_remove_event_translator (ClutterBackend *backend,
ClutterEventTranslator *translator)
{
if (g_list_find (backend->event_translators, translator) == NULL)
return;
backend->event_translators =
g_list_remove (backend->event_translators, translator);
}
/**
* clutter_backend_get_cogl_context: (skip)
* @backend: a #ClutterBackend
@ -795,6 +1237,119 @@ 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
/**
* clutter_set_windowing_backend:
* @backend_type: a comma separated list of windowing backends
*
* Restricts Clutter to only use the specified backend or list of backends.
*
* You can use one of the `CLUTTER_WINDOWING_*` symbols, e.g.
*
* |[<!-- language="C" -->
* clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
* ]|
*
* Will force Clutter to use the X11 windowing and input backend, and terminate
* if the X11 backend could not be initialized successfully.
*
* Since Clutter 1.26, you can also use a comma-separated list of windowing
* system backends to provide a fallback in case backends are not available or
* enabled, e.g.:
*
* |[<!-- language="C" -->
* clutter_set_windowing_backend ("gdk,wayland,x11");
* ]|
*
* Will make Clutter test for the GDK, Wayland, and X11 backends in that order.
*
* You can use the `*` special value to ask Clutter to use the internally
* defined list of backends. For instance:
*
* |[<!-- language="C" -->
* clutter_set_windowing_backend ("x11,wayland,*");
* ]|
*
* Will make Clutter test the X11 and Wayland backends, and then fall back
* to the internal list of available backends.
*
* This function must be called before the first API call to Clutter, including
* clutter_get_option_context()
*
* Since: 1.16
*/
void
clutter_set_windowing_backend (const char *backend_type)
{
g_return_if_fail (backend_type != NULL);
allowed_backends = g_strdup (backend_type);
}
void
clutter_try_set_windowing_backend (const char *backend_type)
{
if (allowed_backends == NULL)
clutter_set_windowing_backend (backend_type);
}
PangoDirection
_clutter_backend_get_keymap_direction (ClutterBackend *backend)
{
ClutterBackendClass *klass;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->get_keymap_direction != NULL)
return klass->get_keymap_direction (backend);
return PANGO_DIRECTION_NEUTRAL;
}
void
_clutter_backend_reset_cogl_framebuffer (ClutterBackend *backend)
{
if (backend->dummy_onscreen == COGL_INVALID_HANDLE)
{
CoglError *internal_error = NULL;
backend->dummy_onscreen = cogl_onscreen_new (backend->cogl_context, 1, 1);
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (backend->dummy_onscreen),
&internal_error))
{
g_critical ("Unable to create dummy onscreen: %s", internal_error->message);
cogl_error_free (internal_error);
return;
}
}
cogl_set_framebuffer (COGL_FRAMEBUFFER (backend->dummy_onscreen));
}
void
clutter_set_allowed_drivers (const char *drivers)
{
@ -807,6 +1362,16 @@ clutter_set_allowed_drivers (const char *drivers)
allowed_drivers = g_strdup (drivers);
}
void
clutter_backend_bell_notify (ClutterBackend *backend)
{
ClutterBackendClass *klass;
klass = CLUTTER_BACKEND_GET_CLASS (backend);
if (klass->bell_notify)
klass->bell_notify (backend);
}
/**
* clutter_backend_get_input_method:
* @backend: the #CLutterBackend
@ -834,51 +1399,3 @@ clutter_backend_set_input_method (ClutterBackend *backend,
{
g_set_object (&backend->input_method, method);
}
ClutterStageWindow *
clutter_backend_get_stage_window (ClutterBackend *backend)
{
return backend->stage_window;
}
/**
* clutter_backend_get_default_seat:
* @backend: the #ClutterBackend
*
* Returns the default seat
*
* Returns: (transfer none): the default seat
**/
ClutterSeat *
clutter_backend_get_default_seat (ClutterBackend *backend)
{
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
return CLUTTER_BACKEND_GET_CLASS (backend)->get_default_seat (backend);
}
void
clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
float fallback_resource_scale)
{
backend->fallback_resource_scale = fallback_resource_scale;
}
float
clutter_backend_get_fallback_resource_scale (ClutterBackend *backend)
{
return backend->fallback_resource_scale;
}
gboolean
clutter_backend_is_display_server (ClutterBackend *backend)
{
return CLUTTER_BACKEND_GET_CLASS (backend)->is_display_server (backend);
}
void
clutter_backend_destroy (ClutterBackend *backend)
{
g_object_run_dispose (G_OBJECT (backend));
g_object_unref (backend);
}

View File

@ -33,9 +33,8 @@
#include <cogl/cogl.h>
#include <clutter/clutter-keymap.h>
#include <clutter/clutter-config.h>
#include <clutter/clutter-types.h>
#include <clutter/clutter-seat.h>
G_BEGIN_DECLS
@ -60,6 +59,9 @@ GType clutter_backend_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterBackend * clutter_get_default_backend (void);
CLUTTER_EXPORT
void clutter_set_windowing_backend (const char *backend_type);
CLUTTER_EXPORT
gdouble clutter_backend_get_resolution (ClutterBackend *backend);
@ -72,15 +74,15 @@ const cairo_font_options_t * clutter_backend_get_font_options (Clutter
CLUTTER_EXPORT
CoglContext * clutter_backend_get_cogl_context (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_bell_notify (ClutterBackend *backend);
CLUTTER_EXPORT
ClutterInputMethod * clutter_backend_get_input_method (ClutterBackend *backend);
CLUTTER_EXPORT
void clutter_backend_set_input_method (ClutterBackend *backend,
ClutterInputMethod *method);
CLUTTER_EXPORT
ClutterSeat * clutter_backend_get_default_seat (ClutterBackend *backend);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -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)

View File

@ -36,7 +36,7 @@ G_BEGIN_DECLS
typedef struct _ClutterBezier ClutterBezier;
ClutterBezier *_clutter_bezier_new (void);
ClutterBezier *_clutter_bezier_new ();
void _clutter_bezier_free (ClutterBezier * b);

View File

@ -49,10 +49,10 @@
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-container.h"
#include "deprecated/clutter-bin-layout.h"
#include "clutter-actor-private.h"
#include "clutter-animatable.h"
#include "clutter-bin-layout.h"
#include "clutter-child-meta.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
@ -406,7 +406,8 @@ get_actor_align_factor (ClutterActorAlign alignment)
static void
clutter_bin_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
gfloat allocation_x, allocation_y;
gfloat available_w, available_h;
@ -514,7 +515,8 @@ clutter_bin_layout_allocate (ClutterLayoutManager *manager,
clutter_actor_allocate_align_fill (child, &child_alloc,
x_align, y_align,
x_fill, y_fill);
x_fill, y_fill,
flags);
}
}
@ -696,3 +698,187 @@ clutter_bin_layout_new (ClutterBinAlignment x_align,
"y-align", y_align,
NULL);
}
/**
* clutter_bin_layout_set_alignment:
* @self: a #ClutterBinLayout
* @child: (allow-none): a child of @container
* @x_align: the horizontal alignment policy to be used for the @child
* inside @container
* @y_align: the vertical aligment policy to be used on the @child
* inside @container
*
* Sets the horizontal and vertical alignment policies to be applied
* to a @child of @self
*
* If @child is %NULL then the @x_align and @y_align values will
* be set as the default alignment policies
*
* Since: 1.2
*
* Deprecated: 1.12: Use the #ClutterActor:x-align and
* #ClutterActor:y-align properties of #ClutterActor instead.
*/
void
clutter_bin_layout_set_alignment (ClutterBinLayout *self,
ClutterActor *child,
ClutterBinAlignment x_align,
ClutterBinAlignment y_align)
{
ClutterBinLayoutPrivate *priv;
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
priv = self->priv;
if (priv->container == NULL)
{
if (child == NULL)
{
set_x_align (self, x_align);
set_y_align (self, y_align);
}
else
g_warning ("The layout of type '%s' must be associated to "
"a ClutterContainer before setting the alignment "
"on its children",
G_OBJECT_TYPE_NAME (self));
return;
}
manager = CLUTTER_LAYOUT_MANAGER (self);
meta = clutter_layout_manager_get_child_meta (manager,
priv->container,
child);
g_assert (CLUTTER_IS_BIN_LAYER (meta));
set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
}
/**
* clutter_bin_layout_get_alignment:
* @self: a #ClutterBinLayout
* @child: (allow-none): a child of @container
* @x_align: (out) (allow-none): return location for the horizontal
* alignment policy
* @y_align: (out) (allow-none): return location for the vertical
* alignment policy
*
* Retrieves the horizontal and vertical alignment policies for
* a child of @self
*
* If @child is %NULL the default alignment policies will be returned
* instead
*
* Since: 1.2
*
* Deprecated: 1.12: Use the #ClutterActor:x-align and the
* #ClutterActor:y-align properties of #ClutterActor instead.
*/
void
clutter_bin_layout_get_alignment (ClutterBinLayout *self,
ClutterActor *child,
ClutterBinAlignment *x_align,
ClutterBinAlignment *y_align)
{
ClutterBinLayoutPrivate *priv;
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
ClutterBinLayer *layer;
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
priv = self->priv;
if (priv->container == NULL)
{
if (child == NULL)
{
if (x_align)
*x_align = priv->x_align;
if (y_align)
*y_align = priv->y_align;
}
else
g_warning ("The layout of type '%s' must be associated to "
"a ClutterContainer before getting the alignment "
"of its children",
G_OBJECT_TYPE_NAME (self));
return;
}
manager = CLUTTER_LAYOUT_MANAGER (self);
meta = clutter_layout_manager_get_child_meta (manager,
priv->container,
child);
g_assert (CLUTTER_IS_BIN_LAYER (meta));
layer = CLUTTER_BIN_LAYER (meta);
if (x_align)
*x_align = layer->x_align;
if (y_align)
*y_align = layer->y_align;
}
/**
* clutter_bin_layout_add:
* @self: a #ClutterBinLayout
* @child: a #ClutterActor
* @x_align: horizontal alignment policy for @child
* @y_align: vertical alignment policy for @child
*
* Adds a #ClutterActor to the container using @self and
* sets the alignment policies for it
*
* This function is equivalent to clutter_container_add_actor()
* and clutter_layout_manager_child_set_property() but it does not
* require a pointer to the #ClutterContainer associated to the
* #ClutterBinLayout
*
* Since: 1.2
*
* Deprecated: 1.12: Use clutter_actor_add_child() instead.
*/
void
clutter_bin_layout_add (ClutterBinLayout *self,
ClutterActor *child,
ClutterBinAlignment x_align,
ClutterBinAlignment y_align)
{
ClutterBinLayoutPrivate *priv;
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
g_return_if_fail (CLUTTER_IS_ACTOR (child));
priv = self->priv;
if (priv->container == NULL)
{
g_warning ("The layout of type '%s' must be associated to "
"a ClutterContainer before adding children",
G_OBJECT_TYPE_NAME (self));
return;
}
clutter_container_add_actor (priv->container, child);
manager = CLUTTER_LAYOUT_MANAGER (self);
meta = clutter_layout_manager_get_child_meta (manager,
priv->container,
child);
g_assert (CLUTTER_IS_BIN_LAYER (meta));
set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
}

View File

@ -38,14 +38,12 @@
*
* |[<!-- language="C" -->
* // source
* rect[0] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[0], &red_color);
* rect[0] = clutter_rectangle_new_with_color (&red_color);
* clutter_actor_set_position (rect[0], x_pos, y_pos);
* clutter_actor_set_size (rect[0], 100, 100);
*
* // second rectangle
* rect[1] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[1], &green_color);
* rect[1] = clutter_rectangle_new_with_color (&green_color);
* clutter_actor_set_size (rect[1], 100, 100);
* clutter_actor_set_opacity (rect[1], 0);
*
@ -55,8 +53,7 @@
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
*
* // third rectangle
* rect[2] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[2], &blue_color);
* rect[2] = clutter_rectangle_new_with_color (&blue_color);
* clutter_actor_set_size (rect[2], 100, 100);
* clutter_actor_set_opacity (rect[2], 0);
*
@ -147,58 +144,6 @@ source_destroyed (ClutterActor *actor,
bind->source = NULL;
}
static void
clutter_bind_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterOrientation direction,
float for_size,
float *minimum_size,
float *natural_size)
{
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
float source_min, source_nat;
if (bind->source == NULL)
return;
/* only these bindings affect the preferred size */
if (!(bind->coordinate == CLUTTER_BIND_WIDTH ||
bind->coordinate == CLUTTER_BIND_HEIGHT ||
bind->coordinate == CLUTTER_BIND_SIZE ||
bind->coordinate == CLUTTER_BIND_ALL))
return;
if (clutter_actor_contains (bind->source, actor))
return;
switch (direction)
{
case CLUTTER_ORIENTATION_HORIZONTAL:
if (bind->coordinate != CLUTTER_BIND_HEIGHT)
{
clutter_actor_get_preferred_width (bind->source, for_size,
&source_min,
&source_nat);
*minimum_size = source_min;
*natural_size = source_nat;
}
break;
case CLUTTER_ORIENTATION_VERTICAL:
if (bind->coordinate != CLUTTER_BIND_WIDTH)
{
clutter_actor_get_preferred_height (bind->source, for_size,
&source_min,
&source_nat);
*minimum_size = source_min;
*natural_size = source_nat;
}
break;
}
}
static void
clutter_bind_constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
@ -207,9 +152,7 @@ clutter_bind_constraint_update_allocation (ClutterConstraint *constraint,
ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (constraint);
gfloat source_width, source_height;
gfloat actor_width, actor_height;
graphene_point3d_t source_position;
source_position = GRAPHENE_POINT3D_INIT (0.f, 0.f, 0.f);
ClutterVertex source_position = { 0., };
if (bind->source == NULL)
return;
@ -383,8 +326,6 @@ clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass)
meta_class->set_actor = clutter_bind_constraint_set_actor;
constraint_class->update_allocation = clutter_bind_constraint_update_allocation;
constraint_class->update_preferred_size = clutter_bind_constraint_update_preferred_size;
/**
* ClutterBindConstraint:source:
*

View File

@ -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);
}
}
@ -235,7 +235,8 @@ clutter_binding_pool_finalize (GObject *gobject)
g_hash_table_destroy (pool->entries_hash);
g_slist_free_full (pool->entries, (GDestroyNotify) binding_entry_free);
g_slist_foreach (pool->entries, (GFunc) binding_entry_free, NULL);
g_slist_free (pool->entries);
G_OBJECT_CLASS (clutter_binding_pool_parent_class)->finalize (gobject);
}

View File

@ -39,6 +39,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-blur-effect.h"
#include "cogl/cogl.h"
@ -79,6 +81,9 @@ struct _ClutterBlurEffect
gint pixel_step_uniform;
gint tex_width;
gint tex_height;
CoglPipeline *pipeline;
};
@ -93,42 +98,19 @@ G_DEFINE_TYPE (ClutterBlurEffect,
clutter_blur_effect,
CLUTTER_TYPE_OFFSCREEN_EFFECT);
static CoglPipeline *
clutter_blur_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterBlurEffect *blur_effect = CLUTTER_BLUR_EFFECT (effect);
if (blur_effect->pixel_step_uniform > -1)
{
float pixel_step[2];
int tex_width, tex_height;
tex_width = cogl_texture_get_width (texture);
tex_height = cogl_texture_get_height (texture);
pixel_step[0] = 1.0f / tex_width;
pixel_step[1] = 1.0f / tex_height;
cogl_pipeline_set_uniform_float (blur_effect->pipeline,
blur_effect->pixel_step_uniform,
2, /* n_components */
1, /* count */
pixel_step);
}
cogl_pipeline_set_layer_texture (blur_effect->pipeline, 0, texture);
return cogl_object_ref (blur_effect->pipeline);
}
static gboolean
clutter_blur_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_blur_effect_pre_paint (ClutterEffect *effect)
{
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
if (self->actor == NULL)
return FALSE;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
@ -142,15 +124,65 @@ clutter_blur_effect_pre_paint (ClutterEffect *effect,
}
parent_class = CLUTTER_EFFECT_CLASS (clutter_blur_effect_parent_class);
return parent_class->pre_paint (effect, node, paint_context);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
if (self->pixel_step_uniform > -1)
{
gfloat pixel_step[2];
pixel_step[0] = 1.0f / self->tex_width;
pixel_step[1] = 1.0f / self->tex_height;
cogl_pipeline_set_uniform_float (self->pipeline,
self->pixel_step_uniform,
2, /* n_components */
1, /* count */
pixel_step);
}
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_blur_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterBlurEffect *self = CLUTTER_BLUR_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
guint8 paint_opacity;
paint_opacity = clutter_actor_get_paint_opacity (self->actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
self->tex_width, self->tex_height);
}
static gboolean
clutter_blur_effect_modify_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
clutter_blur_effect_get_paint_volume (ClutterEffect *effect,
ClutterPaintVolume *volume)
{
gfloat cur_width, cur_height;
graphene_point3d_t origin;
ClutterVertex origin;
clutter_paint_volume_get_origin (volume, &origin);
cur_width = clutter_paint_volume_get_width (volume);
@ -191,10 +223,10 @@ clutter_blur_effect_class_init (ClutterBlurEffectClass *klass)
gobject_class->dispose = clutter_blur_effect_dispose;
effect_class->pre_paint = clutter_blur_effect_pre_paint;
effect_class->modify_paint_volume = clutter_blur_effect_modify_paint_volume;
effect_class->get_paint_volume = clutter_blur_effect_get_paint_volume;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_blur_effect_create_pipeline;
offscreen_class->paint_target = clutter_blur_effect_paint_target;
}
static void
@ -217,7 +249,9 @@ clutter_blur_effect_init (ClutterBlurEffect *self)
cogl_pipeline_add_layer_snippet (klass->base_pipeline, 0, snippet);
cogl_object_unref (snippet);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline,
0, /* layer number */
COGL_TEXTURE_TYPE_2D);
}
self->pipeline = cogl_pipeline_copy (klass->base_pipeline);

View File

@ -1,40 +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_BLUR_PRIVATE_H
#define CLUTTER_BLUR_PRIVATE_H
#include <glib-object.h>
#include <cogl/cogl.h>
G_BEGIN_DECLS
typedef struct _ClutterBlur ClutterBlur;
ClutterBlur * clutter_blur_new (CoglTexture *texture,
float sigma);
void clutter_blur_apply (ClutterBlur *blur);
CoglTexture * clutter_blur_get_texture (ClutterBlur *blur);
void clutter_blur_free (ClutterBlur *blur);
G_END_DECLS
#endif /* CLUTTER_BLUR_PRIVATE_H */

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -105,6 +105,64 @@ void clutter_box_layout_set_pack_start (ClutterBoxLayou
CLUTTER_EXPORT
gboolean clutter_box_layout_get_pack_start (ClutterBoxLayout *layout);
CLUTTER_DEPRECATED_FOR(clutter_box_layout_set_orientation)
void clutter_box_layout_set_vertical (ClutterBoxLayout *layout,
gboolean vertical);
CLUTTER_DEPRECATED_FOR(clutter_box_layout_get_orientation)
gboolean clutter_box_layout_get_vertical (ClutterBoxLayout *layout);
CLUTTER_EXPORT
void clutter_box_layout_pack (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean expand,
gboolean x_fill,
gboolean y_fill,
ClutterBoxAlignment x_align,
ClutterBoxAlignment y_align);
CLUTTER_DEPRECATED
void clutter_box_layout_set_alignment (ClutterBoxLayout *layout,
ClutterActor *actor,
ClutterBoxAlignment x_align,
ClutterBoxAlignment y_align);
CLUTTER_DEPRECATED
void clutter_box_layout_get_alignment (ClutterBoxLayout *layout,
ClutterActor *actor,
ClutterBoxAlignment *x_align,
ClutterBoxAlignment *y_align);
CLUTTER_DEPRECATED
void clutter_box_layout_set_fill (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean x_fill,
gboolean y_fill);
CLUTTER_DEPRECATED
void clutter_box_layout_get_fill (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean *x_fill,
gboolean *y_fill);
CLUTTER_DEPRECATED
void clutter_box_layout_set_expand (ClutterBoxLayout *layout,
ClutterActor *actor,
gboolean expand);
CLUTTER_DEPRECATED
gboolean clutter_box_layout_get_expand (ClutterBoxLayout *layout,
ClutterActor *actor);
CLUTTER_DEPRECATED
void clutter_box_layout_set_use_animations (ClutterBoxLayout *layout,
gboolean animate);
CLUTTER_DEPRECATED
gboolean clutter_box_layout_get_use_animations (ClutterBoxLayout *layout);
CLUTTER_DEPRECATED
void clutter_box_layout_set_easing_mode (ClutterBoxLayout *layout,
gulong mode);
CLUTTER_DEPRECATED
gulong clutter_box_layout_get_easing_mode (ClutterBoxLayout *layout);
CLUTTER_DEPRECATED
void clutter_box_layout_set_easing_duration (ClutterBoxLayout *layout,
guint msecs);
CLUTTER_DEPRECATED
guint clutter_box_layout_get_easing_duration (ClutterBoxLayout *layout);
G_END_DECLS
#endif /* __CLUTTER_BOX_LAYOUT_H__ */

View File

@ -41,6 +41,8 @@
#include <math.h>
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-brightness-contrast-effect.h"
#include <cogl/cogl.h>
@ -67,6 +69,9 @@ struct _ClutterBrightnessContrastEffect
gint brightness_offset_uniform;
gint contrast_uniform;
gint tex_width;
gint tex_height;
CoglPipeline *pipeline;
};
@ -116,34 +121,23 @@ G_DEFINE_TYPE (ClutterBrightnessContrastEffect,
static gboolean
will_have_no_effect (ClutterBrightnessContrastEffect *self)
{
return (G_APPROX_VALUE (self->brightness_red, no_change, FLT_EPSILON) &&
G_APPROX_VALUE (self->brightness_green, no_change, FLT_EPSILON) &&
G_APPROX_VALUE (self->brightness_blue, no_change, FLT_EPSILON) &&
G_APPROX_VALUE (self->contrast_red, no_change, FLT_EPSILON) &&
G_APPROX_VALUE (self->contrast_green, no_change, FLT_EPSILON) &&
G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON));
}
static CoglPipeline *
clutter_brightness_contrast_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterBrightnessContrastEffect *self =
CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return cogl_object_ref (self->pipeline);
return (self->brightness_red == no_change &&
self->brightness_green == no_change &&
self->brightness_blue == no_change &&
self->contrast_red == no_change &&
self->contrast_green == no_change &&
self->contrast_blue == no_change);
}
static gboolean
clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect)
{
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
if (will_have_no_effect (self))
return FALSE;
@ -162,8 +156,45 @@ clutter_brightness_contrast_effect_pre_paint (ClutterEffect *effect,
parent_class =
CLUTTER_EFFECT_CLASS (clutter_brightness_contrast_effect_parent_class);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
return parent_class->pre_paint (effect, node, paint_context);
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_brightness_contrast_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterBrightnessContrastEffect *self = CLUTTER_BRIGHTNESS_CONTRAST_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
ClutterActor *actor;
guint8 paint_opacity;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
paint_opacity = clutter_actor_get_paint_opacity (actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
self->tex_width, self->tex_height);
}
static void
@ -263,7 +294,7 @@ clutter_brightness_contrast_effect_class_init (ClutterBrightnessContrastEffectCl
ClutterOffscreenEffectClass *offscreen_class;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_brightness_contrast_effect_create_pipeline;
offscreen_class->paint_target = clutter_brightness_contrast_effect_paint_target;
effect_class->pre_paint = clutter_brightness_contrast_effect_pre_paint;
@ -407,7 +438,9 @@ clutter_brightness_contrast_effect_init (ClutterBrightnessContrastEffect *self)
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
cogl_object_unref (snippet);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline,
0, /* layer number */
COGL_TEXTURE_TYPE_2D);
}
self->pipeline = cogl_pipeline_copy (klass->base_pipeline);
@ -463,9 +496,9 @@ clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContras
{
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
if (G_APPROX_VALUE (red, effect->brightness_red, FLT_EPSILON) &&
G_APPROX_VALUE (green, effect->brightness_green, FLT_EPSILON) &&
G_APPROX_VALUE (blue, effect->brightness_blue, FLT_EPSILON))
if (red == effect->brightness_red &&
green == effect->brightness_green &&
blue == effect->brightness_blue)
return;
effect->brightness_red = red;
@ -553,9 +586,9 @@ clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastE
{
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
if (G_APPROX_VALUE (red, effect->contrast_red, FLT_EPSILON) &&
G_APPROX_VALUE (green, effect->contrast_green, FLT_EPSILON) &&
G_APPROX_VALUE (blue, effect->contrast_blue, FLT_EPSILON))
if (red == effect->contrast_red &&
green == effect->contrast_green &&
blue == effect->contrast_blue)
return;
effect->contrast_red = red;

View File

@ -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

View File

@ -44,12 +44,13 @@
#include "clutter-build-config.h"
#include <math.h>
#include <cogl/cogl.h>
#include <cairo-gobject.h>
#include "clutter-canvas.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-actor-private.h"
#include "clutter-backend.h"
#include "clutter-cairo.h"
@ -68,7 +69,6 @@ struct _ClutterCanvasPrivate
int width;
int height;
float scale_factor;
CoglTexture *texture;
gboolean dirty;
@ -82,7 +82,6 @@ enum
PROP_WIDTH,
PROP_HEIGHT,
PROP_SCALE_FACTOR,
LAST_PROP
};
@ -98,7 +97,7 @@ enum
static guint canvas_signals[LAST_SIGNAL] = { 0, };
static void clutter_content_iface_init (ClutterContentInterface *iface);
static void clutter_content_iface_init (ClutterContentIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterCanvas, clutter_canvas, G_TYPE_OBJECT,
G_ADD_PRIVATE (ClutterCanvas)
@ -179,19 +178,6 @@ clutter_canvas_set_property (GObject *gobject,
}
break;
case PROP_SCALE_FACTOR:
{
gfloat new_scale_factor = g_value_get_float (value);
if (priv->scale_factor != new_scale_factor)
{
priv->scale_factor = new_scale_factor;
clutter_content_invalidate (CLUTTER_CONTENT (gobject));
}
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@ -216,10 +202,6 @@ clutter_canvas_get_property (GObject *gobject,
g_value_set_int (value, priv->height);
break;
case PROP_SCALE_FACTOR:
g_value_set_float (value, priv->scale_factor);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@ -263,19 +245,6 @@ clutter_canvas_class_init (ClutterCanvasClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
/**
* ClutterCanvas:scale-factor:
*
* The height of the canvas.
*/
obj_props[PROP_SCALE_FACTOR] =
g_param_spec_float ("scale-factor",
P_("Scale Factor"),
P_("The Scale factor of the canvas"),
0.01f, G_MAXFLOAT,
1.0f,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
/**
* ClutterCanvas::draw:
@ -322,14 +291,12 @@ clutter_canvas_init (ClutterCanvas *self)
self->priv->width = -1;
self->priv->height = -1;
self->priv->scale_factor = 1.0f;
}
static void
clutter_canvas_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *root,
ClutterPaintContext *paint_context)
clutter_canvas_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *root)
{
ClutterCanvas *self = CLUTTER_CANVAS (content);
ClutterCanvasPrivate *priv = self->priv;
@ -350,7 +317,7 @@ clutter_canvas_paint_content (ClutterContent *content,
return;
node = clutter_actor_create_texture_paint_node (actor, priv->texture);
clutter_paint_node_set_static_name (node, "Canvas Content");
clutter_paint_node_set_name (node, "Canvas Content");
clutter_paint_node_add_child (root, node);
clutter_paint_node_unref (node);
@ -373,8 +340,8 @@ clutter_canvas_emit_draw (ClutterCanvas *self)
priv->dirty = TRUE;
real_width = ceilf (priv->width * priv->scale_factor);
real_height = ceilf (priv->height * priv->scale_factor);
real_width = priv->width;
real_height = priv->height;
CLUTTER_NOTE (MISC, "Creating Cairo surface with size %d x %d",
priv->width, priv->height);
@ -420,10 +387,6 @@ clutter_canvas_emit_draw (ClutterCanvas *self)
mapped_buffer = FALSE;
}
cairo_surface_set_device_scale (surface,
priv->scale_factor,
priv->scale_factor);
self->priv->cr = cr = cairo_create (surface);
g_signal_emit (self, canvas_signals[DRAW], 0,
@ -485,16 +448,16 @@ clutter_canvas_get_preferred_size (ClutterContent *content,
return FALSE;
if (width != NULL)
*width = ceilf (priv->width * priv->scale_factor);
*width = priv->width;
if (height != NULL)
*height = ceilf (priv->height * priv->scale_factor);
*height = priv->height;
return TRUE;
}
static void
clutter_content_iface_init (ClutterContentInterface *iface)
clutter_content_iface_init (ClutterContentIface *iface)
{
iface->invalidate = clutter_canvas_invalidate;
iface->paint_content = clutter_canvas_paint_content;
@ -597,48 +560,3 @@ clutter_canvas_set_size (ClutterCanvas *canvas,
return clutter_canvas_invalidate_internal (canvas, width, height);
}
/**
* clutter_canvas_set_scale_factor:
* @canvas: a #ClutterCanvas
* @scale: the integer scaling factor of the canvas
*
* Sets the scaling factor of the @canvas, and invalidates the content.
*
* This function will cause the @canvas to be invalidated only
* if the scale factor of the canvas surface has changed.
*/
void
clutter_canvas_set_scale_factor (ClutterCanvas *canvas,
float scale)
{
g_return_if_fail (CLUTTER_IS_CANVAS (canvas));
g_return_if_fail (scale > 0.0f);
if (canvas->priv->scale_factor != scale)
{
canvas->priv->scale_factor = scale;
g_object_freeze_notify (G_OBJECT (canvas));
clutter_content_invalidate (CLUTTER_CONTENT (canvas));
g_object_thaw_notify (G_OBJECT (canvas));
g_object_notify_by_pspec (G_OBJECT (canvas), obj_props[PROP_SCALE_FACTOR]);
}
}
/**
* clutter_canvas_get_scale_factor:
* @canvas: a #ClutterCanvas
*
* Gets the scale factor of the @canvas.
*
* Return value: the current @canvas scale factor or -1 if invalid
*/
float
clutter_canvas_get_scale_factor (ClutterCanvas *canvas)
{
g_return_val_if_fail (CLUTTER_IS_CANVAS (canvas), -1.0f);
return canvas->priv->scale_factor;
}

View File

@ -97,9 +97,9 @@ gboolean clutter_canvas_set_size (ClutterCanvas *
CLUTTER_EXPORT
void clutter_canvas_set_scale_factor (ClutterCanvas *canvas,
float scale);
int scale);
CLUTTER_EXPORT
float clutter_canvas_get_scale_factor (ClutterCanvas *canvas);
int clutter_canvas_get_scale_factor (ClutterCanvas *canvas);
G_END_DECLS

View File

@ -105,8 +105,8 @@ struct _ClutterClickActionPrivate
{
ClutterActor *stage;
gulong event_id;
gulong capture_id;
guint event_id;
guint capture_id;
guint long_press_id;
gint long_press_threshold;
@ -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;
@ -159,8 +159,7 @@ static inline void
click_action_set_pressed (ClutterClickAction *action,
gboolean is_pressed)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
is_pressed = !!is_pressed;
@ -175,8 +174,7 @@ static inline void
click_action_set_held (ClutterClickAction *action,
gboolean is_held)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
is_held = !!is_held;
@ -191,8 +189,7 @@ static gboolean
click_action_emit_long_press (gpointer data)
{
ClutterClickAction *action = data;
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
gboolean result;
@ -205,7 +202,11 @@ click_action_emit_long_press (gpointer data)
CLUTTER_LONG_PRESS_ACTIVATE,
&result);
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
click_action_set_pressed (action, FALSE);
click_action_set_held (action, FALSE);
@ -216,8 +217,7 @@ click_action_emit_long_press (gpointer data)
static inline void
click_action_query_long_press (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
gboolean result = FALSE;
gint timeout;
@ -242,7 +242,6 @@ click_action_query_long_press (ClutterClickAction *action)
if (result)
{
g_clear_handle_id (&priv->long_press_id, g_source_remove);
priv->long_press_id =
clutter_threads_add_timeout (timeout,
click_action_emit_long_press,
@ -253,8 +252,7 @@ click_action_query_long_press (ClutterClickAction *action)
static inline void
click_action_cancel_long_press (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
if (priv->long_press_id != 0)
{
@ -263,7 +261,8 @@ click_action_cancel_long_press (ClutterClickAction *action)
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
g_clear_handle_id (&priv->long_press_id, g_source_remove);
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
g_signal_emit (action, click_signals[LONG_PRESS], 0,
actor,
@ -272,30 +271,12 @@ 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,
ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
gboolean has_button = TRUE;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
@ -316,7 +297,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);
@ -365,8 +346,7 @@ on_captured_event (ClutterActor *stage,
ClutterEvent *event,
ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
ClutterModifierType modifier_state;
gboolean has_button = TRUE;
@ -375,10 +355,6 @@ on_captured_event (ClutterActor *stage,
switch (clutter_event_type (event))
{
case CLUTTER_TOUCH_CANCEL:
clutter_click_action_release (action);
break;
case CLUTTER_TOUCH_END:
has_button = FALSE;
case CLUTTER_BUTTON_RELEASE:
@ -387,7 +363,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;
@ -395,9 +371,17 @@ on_captured_event (ClutterActor *stage,
click_action_cancel_long_press (action);
/* disconnect the capture */
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
g_clear_handle_id (&priv->long_press_id, g_source_remove);
if (priv->long_press_id != 0)
{
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
}
if (!clutter_actor_contains (actor, clutter_event_get_source (event)))
return CLUTTER_EVENT_PROPAGATE;
@ -419,23 +403,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;
@ -451,15 +442,14 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta);
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
if (priv->event_id != 0)
{
ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
if (old_actor != NULL)
g_clear_signal_handler (&priv->event_id, old_actor);
g_signal_handler_disconnect (old_actor, priv->event_id);
priv->event_id = 0;
}
@ -467,13 +457,17 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
if (priv->capture_id != 0)
{
if (priv->stage != NULL)
g_clear_signal_handler (&priv->capture_id, priv->stage);
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
priv->stage = NULL;
}
g_clear_handle_id (&priv->long_press_id, g_source_remove);
if (priv->long_press_id != 0)
{
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
}
click_action_set_pressed (action, FALSE);
click_action_set_held (action, FALSE);
@ -486,28 +480,13 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor);
}
static void
clutter_click_action_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterClickAction *click_action = CLUTTER_CLICK_ACTION (meta);
ClutterActorMetaClass *parent_class =
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class);
if (!is_enabled)
clutter_click_action_release (click_action);
parent_class->set_enabled (meta, is_enabled);
}
static void
clutter_click_action_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
switch (prop_id)
{
@ -531,8 +510,7 @@ clutter_click_action_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
switch (prop_id)
{
@ -561,15 +539,26 @@ clutter_click_action_get_property (GObject *gobject,
static void
clutter_click_action_dispose (GObject *gobject)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
g_clear_signal_handler (&priv->event_id,
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)));
if (priv->event_id)
{
g_signal_handler_disconnect (clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)),
priv->event_id);
priv->event_id = 0;
}
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
g_clear_handle_id (&priv->long_press_id, g_source_remove);
if (priv->long_press_id)
{
g_source_remove (priv->long_press_id);
priv->long_press_id = 0;
}
G_OBJECT_CLASS (clutter_click_action_parent_class)->dispose (gobject);
}
@ -582,7 +571,6 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
meta_class->set_actor = clutter_click_action_set_actor;
meta_class->set_enabled = clutter_click_action_set_enabled;
gobject_class->dispose = clutter_click_action_dispose;
gobject_class->set_property = clutter_click_action_set_property;
@ -674,7 +662,8 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterClickActionClass, clicked),
NULL, NULL, NULL,
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
@ -720,11 +709,9 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
static void
clutter_click_action_init (ClutterClickAction *self)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (self);
priv->long_press_threshold = -1;
priv->long_press_duration = -1;
self->priv = clutter_click_action_get_instance_private (self);
self->priv->long_press_threshold = -1;
self->priv->long_press_duration = -1;
}
/**
@ -764,13 +751,17 @@ clutter_click_action_release (ClutterClickAction *action)
g_return_if_fail (CLUTTER_IS_CLICK_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
priv = action->priv;
if (!priv->is_held)
return;
/* disconnect the capture */
g_clear_signal_handler (&priv->capture_id, priv->stage);
if (priv->capture_id != 0)
{
g_signal_handler_disconnect (priv->stage, priv->capture_id);
priv->capture_id = 0;
}
click_action_cancel_long_press (action);
click_action_set_held (action, FALSE);
@ -790,13 +781,9 @@ clutter_click_action_release (ClutterClickAction *action)
guint
clutter_click_action_get_button (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action);
return priv->press_button;
return action->priv->press_button;
}
/**
@ -812,13 +799,9 @@ clutter_click_action_get_button (ClutterClickAction *action)
ClutterModifierType
clutter_click_action_get_state (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action);
return priv->modifier_state;
return action->priv->modifier_state;
}
/**
@ -836,15 +819,11 @@ clutter_click_action_get_coords (ClutterClickAction *action,
gfloat *press_x,
gfloat *press_y)
{
ClutterClickActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
if (press_x != NULL)
*press_x = priv->press_x;
*press_x = action->priv->press_x;
if (press_y != NULL)
*press_y = priv->press_y;
*press_y = action->priv->press_y;
}

View File

@ -37,13 +37,32 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_CLICK_ACTION (clutter_click_action_get_type ())
#define CLUTTER_TYPE_CLICK_ACTION (clutter_click_action_get_type ())
#define CLUTTER_CLICK_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CLICK_ACTION, ClutterClickAction))
#define CLUTTER_IS_CLICK_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CLICK_ACTION))
#define CLUTTER_CLICK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CLICK_ACTION, ClutterClickActionClass))
#define CLUTTER_IS_CLICK_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CLICK_ACTION))
#define CLUTTER_CLICK_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CLICK_ACTION, ClutterClickActionClass))
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterClickAction, clutter_click_action,
CLUTTER, CLICK_ACTION, ClutterAction);
typedef struct _ClutterClickAction ClutterClickAction;
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
typedef struct _ClutterClickActionClass ClutterClickActionClass;
typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
/**
* ClutterClickAction:
*
* The #ClutterClickAction structure contains
* only private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterClickAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterClickActionPrivate *priv;
};
/**
* ClutterClickActionClass:
@ -78,6 +97,9 @@ struct _ClutterClickActionClass
void (* _clutter_click_action7) (void);
};
CLUTTER_EXPORT
GType clutter_click_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_click_action_new (void);

View File

@ -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"
@ -51,8 +52,6 @@
struct _ClutterClonePrivate
{
ClutterActor *clone_source;
float x_scale, y_scale;
gulong source_destroy_id;
};
@ -120,22 +119,40 @@ 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;
ClutterActorBox box, source_box;
gfloat x_scale, y_scale;
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;
/* get our allocated size */
clutter_actor_get_allocation_box (self, &box);
/* and get the allocated size of the source */
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
/* We need to scale what the clone-source actor paints to fill our own
* allocation...
*/
x_scale = clutter_actor_box_get_width (&box)
/ clutter_actor_box_get_width (&source_box);
y_scale = clutter_actor_box_get_height (&box)
/ clutter_actor_box_get_height (&source_box);
cogl_matrix_scale (matrix, x_scale, y_scale, x_scale);
}
static void
clutter_clone_paint (ClutterActor *actor,
ClutterPaintContext *paint_context)
clutter_clone_paint (ClutterActor *actor)
{
ClutterClone *self = CLUTTER_CLONE (actor);
ClutterClonePrivate *priv = self->priv;
@ -172,7 +189,7 @@ clutter_clone_paint (ClutterActor *actor,
if (clutter_actor_is_realized (priv->clone_source))
{
_clutter_actor_push_clone_paint ();
clutter_actor_paint (priv->clone_source, paint_context);
clutter_actor_paint (priv->clone_source);
_clutter_actor_pop_clone_paint ();
}
@ -195,7 +212,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)
@ -222,51 +239,19 @@ clutter_clone_has_overlaps (ClutterActor *actor)
static void
clutter_clone_allocate (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorClass *parent_class;
ClutterActorBox source_box;
float x_scale, y_scale;
/* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
parent_class->allocate (self, box);
parent_class->allocate (self, box, flags);
if (priv->clone_source == NULL)
return;
/* ClutterActor delays allocating until the actor is shown; however
* we cannot paint it correctly in that case, so force an allocation.
*/
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
!clutter_actor_has_allocation (priv->clone_source))
{
float x = 0.f;
float y = 0.f;
clutter_actor_get_fixed_position (priv->clone_source, &x, &y);
clutter_actor_allocate_preferred_size (priv->clone_source, x, y);
}
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
/* We need to scale what the clone-source actor paints to fill our own
* allocation...
*/
x_scale = clutter_actor_box_get_width (box)
/ clutter_actor_box_get_width (&source_box);
y_scale = clutter_actor_box_get_height (box)
/ clutter_actor_box_get_height (&source_box);
if (!G_APPROX_VALUE (priv->x_scale, x_scale, FLT_EPSILON) ||
!G_APPROX_VALUE (priv->y_scale, y_scale, FLT_EPSILON))
{
priv->x_scale = x_scale;
priv->y_scale = y_scale;
clutter_actor_invalidate_transform (CLUTTER_ACTOR (self));
}
#if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented
* actors, as it will break all invariants
@ -280,7 +265,7 @@ clutter_clone_allocate (ClutterActor *self,
* paint cycle, we can safely give it as much size as it requires
*/
if (clutter_actor_get_parent (priv->clone_source) == NULL)
clutter_actor_allocate_preferred_size (priv->clone_source);
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
#endif
}
@ -372,9 +357,6 @@ static void
clutter_clone_init (ClutterClone *self)
{
self->priv = clutter_clone_get_instance_private (self);
self->priv->x_scale = 1.f;
self->priv->y_scale = 1.f;
}
/**
@ -411,7 +393,8 @@ clutter_clone_set_source_internal (ClutterClone *self,
if (priv->clone_source != NULL)
{
g_clear_signal_handler (&priv->source_destroy_id, priv->clone_source);
g_signal_handler_disconnect (priv->clone_source, priv->source_destroy_id);
priv->source_destroy_id = 0;
_clutter_actor_detach_clone (priv->clone_source, CLUTTER_ACTOR (self));
g_object_unref (priv->clone_source);
priv->clone_source = NULL;

View File

@ -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);
}
/**

View File

@ -39,6 +39,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-colorize-effect.h"
#include "cogl/cogl.h"
@ -57,6 +59,9 @@ struct _ClutterColorizeEffect
gint tint_uniform;
gint tex_width;
gint tex_height;
CoglPipeline *pipeline;
};
@ -99,24 +104,15 @@ G_DEFINE_TYPE (ClutterColorizeEffect,
clutter_colorize_effect,
CLUTTER_TYPE_OFFSCREEN_EFFECT);
static CoglPipeline *
clutter_colorize_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterColorizeEffect *colorize_effect = CLUTTER_COLORIZE_EFFECT (effect);
cogl_pipeline_set_layer_texture (colorize_effect->pipeline, 0, texture);
return cogl_object_ref (colorize_effect->pipeline);
}
static gboolean
clutter_colorize_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_colorize_effect_pre_paint (ClutterEffect *effect)
{
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
@ -130,7 +126,45 @@ clutter_colorize_effect_pre_paint (ClutterEffect *effect,
}
parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class);
return parent_class->pre_paint (effect, node, paint_context);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_colorize_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
ClutterActor *actor;
guint8 paint_opacity;
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
paint_opacity = clutter_actor_get_paint_opacity (actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
self->tex_width, self->tex_height);
}
static void
@ -196,7 +230,7 @@ clutter_colorize_effect_class_init (ClutterColorizeEffectClass *klass)
ClutterOffscreenEffectClass *offscreen_class;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_colorize_effect_create_pipeline;
offscreen_class->paint_target = clutter_colorize_effect_paint_target;
effect_class->pre_paint = clutter_colorize_effect_pre_paint;
@ -259,7 +293,9 @@ clutter_colorize_effect_init (ClutterColorizeEffect *self)
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
cogl_object_unref (snippet);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline,
0, /* layer number */
COGL_TEXTURE_TYPE_2D);
}
self->pipeline = cogl_pipeline_copy (klass->base_pipeline);

View File

@ -0,0 +1,16 @@
#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
@CLUTTER_CONFIG_DEFINES@
G_END_DECLS
#endif /* __CLUTTER_CONFIG_H__ */

View File

@ -30,6 +30,13 @@ gboolean clutter_constraint_update_allocation (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterActorBox *allocation);
void clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterOrientation direction,
float for_size,
float *minimum_size,
float *natural_size);
G_END_DECLS
#endif /* __CLUTTER_CONSTRAINT_PRIVATE_H__ */

View File

@ -48,7 +48,7 @@
* Constraints provide a way to build user interfaces by using
* relations between #ClutterActors, without explicit fixed
* positioning and sizing, similarly to how fluid layout managers like
* #ClutterBoxLayout lay out their children.
* #ClutterBoxLayout and #ClutterTableLayout lay out their children.
*
* Constraints are attached to a #ClutterActor, and are available
* for inspection using clutter_actor_get_constraints().
@ -160,26 +160,28 @@ constraint_update_preferred_size (ClutterConstraint *constraint,
}
static void
clutter_constraint_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
clutter_constraint_notify (GObject *gobject,
GParamSpec *pspec)
{
ClutterActorMetaClass *parent_class =
CLUTTER_ACTOR_META_CLASS (clutter_constraint_parent_class);
ClutterActor *actor;
if (strcmp (pspec->name, "enabled") == 0)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
ClutterActor *actor = clutter_actor_meta_get_actor (meta);
actor = clutter_actor_meta_get_actor (meta);
if (actor)
clutter_actor_queue_relayout (actor);
if (actor != NULL)
clutter_actor_queue_relayout (actor);
}
parent_class->set_enabled (meta, is_enabled);
if (G_OBJECT_CLASS (clutter_constraint_parent_class)->notify != NULL)
G_OBJECT_CLASS (clutter_constraint_parent_class)->notify (gobject, pspec);
}
static void
clutter_constraint_class_init (ClutterConstraintClass *klass)
{
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
actor_meta_class->set_enabled = clutter_constraint_set_enabled;
gobject_class->notify = clutter_constraint_notify;
klass->update_allocation = constraint_update_allocation;
klass->update_preferred_size = constraint_update_preferred_size;
@ -220,17 +222,6 @@ clutter_constraint_update_allocation (ClutterConstraint *constraint,
return !clutter_actor_box_equal (allocation, &old_alloc);
}
/**
* clutter_constraint_update_preferred_size:
* @constraint: a #ClutterConstraint
* @actor: a #ClutterActor
* @direction: a #ClutterOrientation
* @for_size: the size in the opposite direction
* @minimum_size: (inout): the minimum size to modify
* @natural_size: (inout): the natural size to modify
*
* Asks the @constraint to update the size request of a #ClutterActor.
*/
void
clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,

View File

@ -99,14 +99,6 @@ struct _ClutterConstraintClass
CLUTTER_EXPORT
GType clutter_constraint_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
void clutter_constraint_update_preferred_size (ClutterConstraint *constraint,
ClutterActor *actor,
ClutterOrientation direction,
float for_size,
float *minimum_size,
float *natural_size);
/* ClutterActor API */
CLUTTER_EXPORT
void clutter_actor_add_constraint (ClutterActor *self,

View File

@ -37,7 +37,6 @@
#include "clutter-actor-private.h"
#include "clutter-child-meta.h"
#include "clutter-container-private.h"
#include "clutter-debug.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
@ -119,6 +118,37 @@ container_real_remove (ClutterContainer *container,
clutter_actor_remove_child (CLUTTER_ACTOR (container), actor);
}
typedef struct {
ClutterCallback callback;
gpointer data;
} ForeachClosure;
static gboolean
foreach_cb (ClutterActor *actor,
gpointer data)
{
ForeachClosure *clos = data;
clos->callback (actor, clos->data);
return TRUE;
}
static void
container_real_foreach (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
ForeachClosure clos;
clos.callback = callback;
clos.data = user_data;
_clutter_actor_foreach_child (CLUTTER_ACTOR (container),
foreach_cb,
&clos);
}
static void
container_real_raise (ClutterContainer *container,
ClutterActor *child,
@ -167,7 +197,8 @@ clutter_container_default_init (ClutterContainerInterface *iface)
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterContainerIface, actor_added),
NULL, NULL, NULL,
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
/**
@ -185,7 +216,8 @@ clutter_container_default_init (ClutterContainerInterface *iface)
iface_type,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterContainerIface, actor_removed),
NULL, NULL, NULL,
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
@ -213,6 +245,7 @@ clutter_container_default_init (ClutterContainerInterface *iface)
iface->add = container_real_add;
iface->remove = container_real_remove;
iface->foreach = container_real_foreach;
iface->raise = container_real_raise;
iface->lower = container_real_lower;
iface->sort_depth_order = container_real_sort_depth_order;
@ -385,6 +418,33 @@ clutter_container_add_actor (ClutterContainer *container,
container_add_actor (container, actor);
}
/**
* clutter_container_add_valist: (skip)
* @container: a #ClutterContainer
* @first_actor: the first #ClutterActor to add
* @var_args: list of actors to add, followed by %NULL
*
* Alternative va_list version of clutter_container_add().
*
* This function will call #ClutterContainerIface.add(), which is a
* deprecated virtual function. The default implementation will
* call clutter_actor_add_child().
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_actor_add_child() instead.
*/
void
clutter_container_add_valist (ClutterContainer *container,
ClutterActor *first_actor,
va_list var_args)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
container_add_valist (container, first_actor, var_args);
}
/**
* clutter_container_remove: (skip)
* @container: a #ClutterContainer
@ -448,6 +508,42 @@ clutter_container_remove_actor (ClutterContainer *container,
container_remove_actor (container, actor);
}
/**
* clutter_container_remove_valist: (skip)
* @container: a #ClutterContainer
* @first_actor: the first #ClutterActor to add
* @var_args: list of actors to remove, followed by %NULL
*
* Alternative va_list version of clutter_container_remove().
*
* This function will call #ClutterContainerIface.remove(), which is a
* deprecated virtual function. The default implementation will call
* clutter_actor_remove_child().
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_actor_remove_child() instead.
*/
void
clutter_container_remove_valist (ClutterContainer *container,
ClutterActor *first_actor,
va_list var_args)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
container_remove_valist (container, first_actor, var_args);
}
static void
get_children_cb (ClutterActor *child,
gpointer data)
{
GList **children = data;
*children = g_list_prepend (*children, child);
}
/**
* clutter_container_get_children:
* @container: a #ClutterContainer
@ -465,9 +561,108 @@ clutter_container_remove_actor (ClutterContainer *container,
GList *
clutter_container_get_children (ClutterContainer *container)
{
GList *retval;
g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
return clutter_actor_get_children (CLUTTER_ACTOR (container));
retval = NULL;
clutter_container_foreach (container, get_children_cb, &retval);
return g_list_reverse (retval);
}
/**
* clutter_container_foreach:
* @container: a #ClutterContainer
* @callback: (scope call): a function to be called for each child
* @user_data: data to be passed to the function, or %NULL
*
* Calls @callback for each child of @container that was added
* by the application (with clutter_container_add_actor()). Does
* not iterate over "internal" children that are part of the
* container's own implementation, if any.
*
* This function calls the #ClutterContainerIface.foreach()
* virtual function, which has been deprecated.
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_actor_get_first_child() or
* clutter_actor_get_last_child() to retrieve the beginning of
* the list of children, and clutter_actor_get_next_sibling()
* and clutter_actor_get_previous_sibling() to iterate over it;
* alternatively, use the #ClutterActorIter API.
*/
void
clutter_container_foreach (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (callback != NULL);
#ifdef CLUTTER_ENABLE_DEBUG
if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
{
ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
if (iface->foreach != container_real_foreach)
_clutter_diagnostic_message ("The ClutterContainer::foreach() "
"virtual function has been deprecated "
"and it should not be overridden by "
"newly written code");
}
#endif /* CLUTTER_ENABLE_DEBUG */
CLUTTER_CONTAINER_GET_IFACE (container)->foreach (container,
callback,
user_data);
}
/**
* clutter_container_foreach_with_internals:
* @container: a #ClutterContainer
* @callback: (scope call): a function to be called for each child
* @user_data: data to be passed to the function, or %NULL
*
* Calls @callback for each child of @container, including "internal"
* children built in to the container itself that were never added
* by the application.
*
* This function calls the #ClutterContainerIface.foreach_with_internals()
* virtual function, which has been deprecated.
*
* Since: 1.0
*
* Deprecated: 1.10: See clutter_container_foreach().
*/
void
clutter_container_foreach_with_internals (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
ClutterContainerIface *iface;
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (callback != NULL);
iface = CLUTTER_CONTAINER_GET_IFACE (container);
#ifdef CLUTTER_ENABLE_DEBUG
if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
{
if (iface->foreach_with_internals != NULL)
_clutter_diagnostic_message ("The ClutterContainer::foreach_with_internals() "
"virtual function has been deprecated "
"and it should not be overridden by "
"newly written code");
}
#endif /* CLUTTER_ENABLE_DEBUG */
if (iface->foreach_with_internals != NULL)
iface->foreach_with_internals (container, callback, user_data);
else
iface->foreach (container, callback, user_data);
}
/**
@ -1251,23 +1446,3 @@ clutter_container_child_notify (ClutterContainer *container,
child,
pspec);
}
void
_clutter_container_emit_actor_added (ClutterContainer *container,
ClutterActor *actor)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_signal_emit (container, container_signals[ACTOR_ADDED], 0, actor);
}
void
_clutter_container_emit_actor_removed (ClutterContainer *container,
ClutterActor *actor)
{
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_signal_emit (container, container_signals[ACTOR_REMOVED], 0, actor);
}

View File

@ -59,6 +59,14 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
* function is deprecated, and it should not be overridden.
* @remove: virtual function for removing an actor from the container. This
* virtual function is deprecated, and it should not be overridden.
* @foreach: virtual function for iterating over the container's children.
* This virtual function is deprecated, and it should not be overridden.
* @foreach_with_internals: virtual functions for iterating over the
* container's children, both added using the #ClutterContainer API
* and internal children. The implementation of this virtual function
* is required only if the #ClutterContainer implementation has
* internal children. This virtual function is deprecated, and it should
* not be overridden.
* @raise: virtual function for raising a child. This virtual function is
* deprecated and it should not be overridden.
* @lower: virtual function for lowering a child. This virtual function is
@ -74,13 +82,13 @@ 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
* @child_notify: class handler for #ClutterContainer::child-notify
*
* Base interface for container actors. The @add and @remove
* Base interface for container actors. The @add, @remove and @foreach
* virtual functions must be provided by any implementation; the other
* virtual functions are optional.
*
@ -96,6 +104,13 @@ struct _ClutterContainerIface
ClutterActor *actor);
void (* remove) (ClutterContainer *container,
ClutterActor *actor);
void (* foreach) (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data);
void (* foreach_with_internals) (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data);
/* child stacking */
void (* raise) (ClutterContainer *container,

View File

@ -34,10 +34,9 @@ void _clutter_content_attached (ClutterContent *conte
void _clutter_content_detached (ClutterContent *content,
ClutterActor *actor);
void _clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
void _clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node);
G_END_DECLS

View File

@ -38,13 +38,14 @@
#include "clutter-build-config.h"
#include "clutter-actor-private.h"
#include "clutter-content-private.h"
#include "clutter-debug.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
typedef struct _ClutterContentIface ClutterContentInterface;
enum
{
ATTACHED,
@ -91,15 +92,9 @@ clutter_content_real_invalidate (ClutterContent *content)
}
static void
clutter_content_real_invalidate_size (ClutterContent *content)
{
}
static void
clutter_content_real_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *context,
ClutterPaintContext *paint_context)
clutter_content_real_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *context)
{
}
@ -113,7 +108,6 @@ clutter_content_default_init (ClutterContentInterface *iface)
iface->attached = clutter_content_real_attached;
iface->detached = clutter_content_real_detached;
iface->invalidate = clutter_content_real_invalidate;
iface->invalidate_size = clutter_content_real_invalidate_size;
/**
* ClutterContent::attached:
@ -129,8 +123,9 @@ clutter_content_default_init (ClutterContentInterface *iface)
g_signal_new (I_("attached"),
G_TYPE_FROM_INTERFACE (iface),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterContentInterface, attached),
NULL, NULL, NULL,
G_STRUCT_OFFSET (ClutterContentIface, attached),
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
@ -148,8 +143,9 @@ clutter_content_default_init (ClutterContentInterface *iface)
g_signal_new (I_("detached"),
G_TYPE_FROM_INTERFACE (iface),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ClutterContentInterface, detached),
NULL, NULL, NULL,
G_STRUCT_OFFSET (ClutterContentIface, detached),
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
}
@ -192,45 +188,6 @@ clutter_content_invalidate (ClutterContent *content)
}
}
/**
* clutter_content_invalidate_size:
* @content: a #ClutterContent
*
* Signals that @content's size changed. Attached actors with request mode
* set to %CLUTTER_REQUEST_CONTENT_SIZE will have a relayout queued.
*
* Attached actors with other request modes are not redrawn. To redraw them
* too, use clutter_content_invalidate().
*/
void
clutter_content_invalidate_size (ClutterContent *content)
{
ClutterActor *actor;
GHashTable *actors;
GHashTableIter iter;
g_return_if_fail (CLUTTER_IS_CONTENT (content));
CLUTTER_CONTENT_GET_IFACE (content)->invalidate_size (content);
actors = g_object_get_qdata (G_OBJECT (content), quark_content_actors);
if (actors == NULL)
return;
g_hash_table_iter_init (&iter, actors);
while (g_hash_table_iter_next (&iter, (gpointer *) &actor, NULL))
{
ClutterRequestMode request_mode;
g_assert (actor != NULL);
request_mode = clutter_actor_get_request_mode (actor);
if (request_mode == CLUTTER_REQUEST_CONTENT_SIZE)
_clutter_actor_queue_only_relayout (actor);
}
}
/*< private >
* _clutter_content_attached:
* @content: a #ClutterContent
@ -242,7 +199,7 @@ clutter_content_invalidate_size (ClutterContent *content)
* is associated to a #ClutterContent, to set up a backpointer from
* the @content to the @actor.
*
* This function will invoke the #ClutterContentInterface.attached() virtual
* This function will invoke the #ClutterContentIface.attached() virtual
* function.
*/
void
@ -276,7 +233,7 @@ _clutter_content_attached (ClutterContent *content,
* This function should be used internally every time a #ClutterActor
* removes the association with a #ClutterContent.
*
* This function will invoke the #ClutterContentInterface.detached() virtual
* This function will invoke the #ClutterContentIface.detached() virtual
* function.
*/
void
@ -301,22 +258,19 @@ _clutter_content_detached (ClutterContent *content,
* _clutter_content_paint_content:
* @content: a #ClutterContent
* @actor: a #ClutterActor
* @node: a #ClutterPaintNode
* @paint_context: a #ClutterPaintContext
* @context: a #ClutterPaintNode
*
* Creates the render tree for the @content and @actor.
*
* This function will invoke the #ClutterContentInterface.paint_content()
* This function will invoke the #ClutterContentIface.paint_content()
* virtual function.
*/
void
_clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
_clutter_content_paint_content (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node)
{
CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node,
paint_context);
CLUTTER_CONTENT_GET_IFACE (content)->paint_content (content, actor, node);
}
/**

View File

@ -33,13 +33,24 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_CONTENT (clutter_content_get_type ())
#define CLUTTER_TYPE_CONTENT (clutter_content_get_type ())
#define CLUTTER_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CONTENT, ClutterContent))
#define CLUTTER_IS_CONTENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CONTENT))
#define CLUTTER_CONTENT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_CONTENT, ClutterContentIface))
CLUTTER_EXPORT
G_DECLARE_INTERFACE (ClutterContent, clutter_content, CLUTTER, CONTENT, GObject)
typedef struct _ClutterContentIface ClutterContentIface;
/**
* ClutterContentInterface:
* ClutterContent:
*
* The #ClutterContent structure is an opaque type
* whose members cannot be acccessed directly.
*
* Since: 1.10
*/
/**
* ClutterContentIface:
* @get_preferred_size: virtual function; should be overridden by subclasses
* of #ClutterContent that have a natural size
* @paint_content: virtual function; called each time the content needs to
@ -51,12 +62,12 @@ G_DECLARE_INTERFACE (ClutterContent, clutter_content, CLUTTER, CONTENT, GObject)
* @invalidate: virtual function; called each time a #ClutterContent state
* is changed.
*
* The #ClutterContentInterface structure contains only
* The #ClutterContentIface structure contains only
* private data.
*
* Since: 1.10
*/
struct _ClutterContentInterface
struct _ClutterContentIface
{
/*< private >*/
GTypeInterface g_iface;
@ -65,10 +76,9 @@ struct _ClutterContentInterface
gboolean (* get_preferred_size) (ClutterContent *content,
gfloat *width,
gfloat *height);
void (* paint_content) (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node,
ClutterPaintContext *paint_context);
void (* paint_content) (ClutterContent *content,
ClutterActor *actor,
ClutterPaintNode *node);
void (* attached) (ClutterContent *content,
ClutterActor *actor);
@ -76,10 +86,11 @@ struct _ClutterContentInterface
ClutterActor *actor);
void (* invalidate) (ClutterContent *content);
void (* invalidate_size) (ClutterContent *content);
};
CLUTTER_EXPORT
GType clutter_content_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
gboolean clutter_content_get_preferred_size (ClutterContent *content,
gfloat *width,
@ -87,9 +98,6 @@ gboolean clutter_content_get_preferred_size (ClutterContent *content
CLUTTER_EXPORT
void clutter_content_invalidate (ClutterContent *content);
CLUTTER_EXPORT
void clutter_content_invalidate_size (ClutterContent *content);
G_END_DECLS
#endif /* __CLUTTER_CONTENT_H__ */

View File

@ -1,92 +0,0 @@
/*
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
* Copyright (C) 2020 Red Hat Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter-damage-history.h"
#define DAMAGE_HISTORY_LENGTH 0x10
struct _ClutterDamageHistory
{
cairo_region_t *damages[DAMAGE_HISTORY_LENGTH];
int index;
};
ClutterDamageHistory *
clutter_damage_history_new (void)
{
ClutterDamageHistory *history;
history = g_new0 (ClutterDamageHistory, 1);
return history;
}
void
clutter_damage_history_free (ClutterDamageHistory *history)
{
int i;
for (i = 0; i < G_N_ELEMENTS (history->damages); i++)
g_clear_pointer (&history->damages[i], cairo_region_destroy);
g_free (history);
}
gboolean
clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
int age)
{
if (age >= DAMAGE_HISTORY_LENGTH ||
age < 1)
return FALSE;
if (!clutter_damage_history_lookup (history, age))
return FALSE;
return TRUE;
}
void
clutter_damage_history_record (ClutterDamageHistory *history,
const cairo_region_t *damage)
{
g_clear_pointer (&history->damages[history->index], cairo_region_destroy);
history->damages[history->index] = cairo_region_copy (damage);
}
static inline int
step_damage_index (int current,
int diff)
{
return (current + diff) & (DAMAGE_HISTORY_LENGTH - 1);
}
void
clutter_damage_history_step (ClutterDamageHistory *history)
{
history->index = step_damage_index (history->index, 1);
}
const cairo_region_t *
clutter_damage_history_lookup (ClutterDamageHistory *history,
int age)
{
return history->damages[step_damage_index (history->index, -age)];
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
* Copyright (C) 2020 Red Hat Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_DAMAGE_HISTORY_H
#define CLUTTER_DAMAGE_HISTORY_H
#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);
#endif /* CLUTTER_DAMAGE_HISTORY_H */

View File

@ -6,6 +6,42 @@
G_BEGIN_DECLS
typedef enum {
CLUTTER_DEBUG_MISC = 1 << 0,
CLUTTER_DEBUG_ACTOR = 1 << 1,
CLUTTER_DEBUG_TEXTURE = 1 << 2,
CLUTTER_DEBUG_EVENT = 1 << 3,
CLUTTER_DEBUG_PAINT = 1 << 4,
CLUTTER_DEBUG_PANGO = 1 << 5,
CLUTTER_DEBUG_BACKEND = 1 << 6,
CLUTTER_DEBUG_SCHEDULER = 1 << 7,
CLUTTER_DEBUG_SCRIPT = 1 << 8,
CLUTTER_DEBUG_SHADER = 1 << 9,
CLUTTER_DEBUG_MULTISTAGE = 1 << 10,
CLUTTER_DEBUG_ANIMATION = 1 << 11,
CLUTTER_DEBUG_LAYOUT = 1 << 12,
CLUTTER_DEBUG_PICK = 1 << 13,
CLUTTER_DEBUG_EVENTLOOP = 1 << 14,
CLUTTER_DEBUG_CLIPPING = 1 << 15,
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16
} ClutterDebugFlag;
typedef enum {
CLUTTER_DEBUG_NOP_PICKING = 1 << 0,
CLUTTER_DEBUG_DUMP_PICK_BUFFERS = 1 << 1
} ClutterPickDebugFlag;
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
} ClutterDrawDebugFlag;
#ifdef CLUTTER_ENABLE_DEBUG
#define CLUTTER_HAS_DEBUG(type) ((clutter_debug_flags & CLUTTER_DEBUG_##type) != FALSE)
@ -41,12 +77,11 @@ 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);
va_list var_args);
void _clutter_debug_message (const char *format,
...) G_GNUC_PRINTF (1, 2);
...);
G_END_DECLS

View File

@ -53,16 +53,14 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "clutter-deform-effect.h"
#include <cogl/cogl.h>
#include "clutter-color.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-offscreen-effect-private.h"
#include "clutter-paint-node.h"
#include "clutter-paint-nodes.h"
#include "clutter-private.h"
#define DEFAULT_N_TILES 32
@ -130,9 +128,10 @@ clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect,
}
static void
vbo_invalidate (ClutterActor *actor,
GParamSpec *pspec,
ClutterDeformEffect *effect)
vbo_invalidate (ClutterActor *actor,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
ClutterDeformEffect *effect)
{
effect->priv->is_dirty = TRUE;
}
@ -148,7 +147,7 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
ClutterActor *old_actor = clutter_actor_meta_get_actor (meta);
if (old_actor != NULL)
g_clear_signal_handler (&priv->allocation_id, old_actor);
g_signal_handler_disconnect (old_actor, priv->allocation_id);
priv->allocation_id = 0;
}
@ -157,7 +156,7 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
* changes
*/
if (actor != NULL)
priv->allocation_id = g_signal_connect (actor, "notify::allocation",
priv->allocation_id = g_signal_connect (actor, "allocation-changed",
G_CALLBACK (vbo_invalidate),
meta);
@ -167,17 +166,18 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
}
static void
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
ClutterDeformEffectPrivate *priv = self->priv;
CoglHandle material;
CoglPipeline *pipeline;
CoglDepthState depth_state;
CoglFramebuffer *fb = cogl_get_draw_framebuffer ();
if (priv->is_dirty)
{
ClutterRect rect;
gboolean mapped_buffer;
CoglVertexP3T2C4 *verts;
ClutterActor *actor;
@ -191,7 +191,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
/* if we don't have a target size, fall back to the actor's
* allocation, though wrong it might be
*/
if (!clutter_offscreen_effect_get_target_size (effect, &width, &height))
if (clutter_offscreen_effect_get_target_rect (effect, &rect))
{
width = clutter_rect_get_width (&rect);
height = clutter_rect_get_height (&rect);
}
else
clutter_actor_get_size (actor, &width, &height);
/* XXX ideally, the sub-classes should tell us what they
@ -271,12 +276,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
priv->is_dirty = FALSE;
}
pipeline = clutter_offscreen_effect_get_pipeline (effect);
material = clutter_offscreen_effect_get_target (effect);
pipeline = COGL_PIPELINE (material);
/* enable depth testing */
cogl_depth_state_init (&depth_state);
cogl_depth_state_set_test_enabled (&depth_state, TRUE);
cogl_depth_state_set_test_function (&depth_state, COGL_DEPTH_TEST_FUNCTION_LEQUAL);
cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL);
/* enable backface culling if we have a back material */
@ -285,22 +290,12 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
COGL_PIPELINE_CULL_FACE_MODE_BACK);
/* draw the front */
if (pipeline != NULL)
{
ClutterPaintNode *front_node;
front_node = clutter_pipeline_node_new (pipeline);
clutter_paint_node_set_static_name (front_node,
"ClutterDeformEffect (front)");
clutter_paint_node_add_child (node, front_node);
clutter_paint_node_add_primitive (front_node, priv->primitive);
clutter_paint_node_unref (front_node);
}
if (material != NULL)
cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);
/* draw the back */
if (priv->back_pipeline != NULL)
{
ClutterPaintNode *back_node;
CoglPipeline *back_pipeline;
/* We probably shouldn't be modifying the user's material so
@ -310,30 +305,20 @@ clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect,
cogl_pipeline_set_cull_face_mode (back_pipeline,
COGL_PIPELINE_CULL_FACE_MODE_FRONT);
cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);
back_node = clutter_pipeline_node_new (back_pipeline);
clutter_paint_node_set_static_name (back_node,
"ClutterDeformEffect (back)");
clutter_paint_node_add_child (node, back_node);
clutter_paint_node_add_primitive (back_node, priv->primitive);
clutter_paint_node_unref (back_node);
cogl_object_unref (back_pipeline);
}
if (G_UNLIKELY (priv->lines_primitive != NULL))
{
const ClutterColor *red;
ClutterPaintNode *lines_node;
red = clutter_color_get_static (CLUTTER_COLOR_RED);
lines_node = clutter_color_node_new (red);
clutter_paint_node_set_static_name (lines_node,
"ClutterDeformEffect (lines)");
clutter_paint_node_add_child (node, lines_node);
clutter_paint_node_add_primitive (lines_node, priv->lines_primitive);
clutter_paint_node_unref (lines_node);
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
cogl_framebuffer_draw_primitive (fb, lines_pipeline,
priv->lines_primitive);
cogl_object_unref (lines_pipeline);
}
}

View File

@ -3,7 +3,42 @@
#define __CLUTTER_DEPRECATED_H_INSIDE__
#include "deprecated/clutter-actor.h"
#include "deprecated/clutter-alpha.h"
#include "deprecated/clutter-animatable.h"
#include "deprecated/clutter-animation.h"
#include "deprecated/clutter-animator.h"
#include "deprecated/clutter-backend.h"
#include "deprecated/clutter-behaviour.h"
#include "deprecated/clutter-behaviour-depth.h"
#include "deprecated/clutter-behaviour-ellipse.h"
#include "deprecated/clutter-behaviour-opacity.h"
#include "deprecated/clutter-behaviour-path.h"
#include "deprecated/clutter-behaviour-rotate.h"
#include "deprecated/clutter-behaviour-scale.h"
#include "deprecated/clutter-bin-layout.h"
#include "deprecated/clutter-box.h"
#include "deprecated/clutter-cairo-texture.h"
#include "deprecated/clutter-container.h"
#include "deprecated/clutter-frame-source.h"
#include "deprecated/clutter-group.h"
#include "deprecated/clutter-input-device.h"
#include "deprecated/clutter-keysyms.h"
#include "deprecated/clutter-list-model.h"
#include "deprecated/clutter-main.h"
#include "deprecated/clutter-media.h"
#include "deprecated/clutter-model.h"
#include "deprecated/clutter-rectangle.h"
#include "deprecated/clutter-score.h"
#include "deprecated/clutter-shader.h"
#include "deprecated/clutter-stage-manager.h"
#include "deprecated/clutter-stage.h"
#include "deprecated/clutter-state.h"
#include "deprecated/clutter-table-layout.h"
#include "deprecated/clutter-texture.h"
#include "deprecated/clutter-timeline.h"
#include "deprecated/clutter-timeout-pool.h"
#include "deprecated/clutter-util.h"
#undef __CLUTTER_DEPRECATED_H_INSIDE__

View File

@ -28,7 +28,7 @@
* @see_also: #ClutterEffect, #ClutterOffscreenEffect
*
* #ClutterDesaturateEffect is a sub-class of #ClutterEffect that
* desaturates the color of an actor and its contents. The strength
* desaturates the color of an actor and its contents. The strenght
* of the desaturation effect is controllable and animatable through
* the #ClutterDesaturateEffect:factor property.
*
@ -41,6 +41,8 @@
#include "clutter-build-config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include <math.h>
#include "clutter-desaturate-effect.h"
@ -109,25 +111,15 @@ G_DEFINE_TYPE (ClutterDesaturateEffect,
clutter_desaturate_effect,
CLUTTER_TYPE_OFFSCREEN_EFFECT);
static CoglPipeline *
clutter_desaturate_effect_create_pipeline (ClutterOffscreenEffect *effect,
CoglTexture *texture)
{
ClutterDesaturateEffect *desaturate_effect =
CLUTTER_DESATURATE_EFFECT (effect);
cogl_pipeline_set_layer_texture (desaturate_effect->pipeline, 0, texture);
return cogl_object_ref (desaturate_effect->pipeline);
}
static gboolean
clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
ClutterPaintNode *node,
ClutterPaintContext *paint_context)
clutter_desaturate_effect_pre_paint (ClutterEffect *effect)
{
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
ClutterEffectClass *parent_class;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
@ -141,7 +133,50 @@ clutter_desaturate_effect_pre_paint (ClutterEffect *effect,
}
parent_class = CLUTTER_EFFECT_CLASS (clutter_desaturate_effect_parent_class);
return parent_class->pre_paint (effect, node, paint_context);
if (parent_class->pre_paint (effect))
{
ClutterOffscreenEffect *offscreen_effect =
CLUTTER_OFFSCREEN_EFFECT (effect);
CoglHandle texture;
texture = clutter_offscreen_effect_get_texture (offscreen_effect);
self->tex_width = cogl_texture_get_width (texture);
self->tex_height = cogl_texture_get_height (texture);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
return TRUE;
}
else
return FALSE;
}
static void
clutter_desaturate_effect_paint_target (ClutterOffscreenEffect *effect)
{
ClutterDesaturateEffect *self = CLUTTER_DESATURATE_EFFECT (effect);
CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
ClutterActor *actor;
CoglHandle texture;
guint8 paint_opacity;
texture = clutter_offscreen_effect_get_texture (effect);
cogl_pipeline_set_layer_texture (self->pipeline, 0, texture);
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
paint_opacity = clutter_actor_get_paint_opacity (actor);
cogl_pipeline_set_color4ub (self->pipeline,
paint_opacity,
paint_opacity,
paint_opacity,
paint_opacity);
cogl_framebuffer_draw_rectangle (framebuffer,
self->pipeline,
0, 0,
cogl_texture_get_width (texture),
cogl_texture_get_height (texture));
}
static void
@ -216,7 +251,7 @@ clutter_desaturate_effect_class_init (ClutterDesaturateEffectClass *klass)
ClutterOffscreenEffectClass *offscreen_class;
offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
offscreen_class->create_pipeline = clutter_desaturate_effect_create_pipeline;
offscreen_class->paint_target = clutter_desaturate_effect_paint_target;
effect_class->pre_paint = clutter_desaturate_effect_pre_paint;
@ -262,7 +297,9 @@ clutter_desaturate_effect_init (ClutterDesaturateEffect *self)
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
cogl_object_unref (snippet);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
cogl_pipeline_set_layer_null_texture (klass->base_pipeline,
0, /* layer number */
COGL_TEXTURE_TYPE_2D);
}
self->pipeline = cogl_pipeline_copy (klass->base_pipeline);

View File

@ -0,0 +1,281 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DEVICE_MANAGER_PRIVATE_H__
#define __CLUTTER_DEVICE_MANAGER_PRIVATE_H__
#include <clutter/clutter-backend.h>
#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-event.h>
G_BEGIN_DECLS
typedef struct _ClutterAxisInfo
{
ClutterInputAxis axis;
gdouble min_axis;
gdouble max_axis;
gdouble min_value;
gdouble max_value;
gdouble resolution;
} ClutterAxisInfo;
typedef struct _ClutterKeyInfo
{
guint keyval;
ClutterModifierType modifiers;
} ClutterKeyInfo;
typedef struct _ClutterScrollInfo
{
guint axis_id;
ClutterScrollDirection direction;
gdouble increment;
gdouble last_value;
guint last_value_valid : 1;
} ClutterScrollInfo;
typedef struct _ClutterTouchInfo
{
ClutterEventSequence *sequence;
ClutterActor *actor;
gfloat current_x;
gfloat current_y;
} ClutterTouchInfo;
struct _ClutterInputDevice
{
GObject parent_instance;
gint id;
ClutterInputDeviceType device_type;
ClutterInputMode device_mode;
gchar *device_name;
ClutterDeviceManager *device_manager;
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;
GHashTable *sequence_grab_actors;
GHashTable *inv_sequence_grab_actors;
/* the current click count */
gint click_count;
/* the stage the device is on */
ClutterStage *stage;
/* the current state */
gfloat current_x;
gfloat current_y;
guint32 current_time;
gint current_button_number;
ClutterModifierType current_state;
/* the current touch points states */
GHashTable *touch_sequences_info;
/* the previous state, used for click count generation */
gint previous_x;
gint previous_y;
guint32 previous_time;
gint previous_button_number;
ClutterModifierType previous_state;
GArray *axes;
guint n_keys;
GArray *keys;
GArray *scroll_info;
gchar *vendor_id;
gchar *product_id;
gchar *node_path;
GPtrArray *tools;
gint n_rings;
gint n_strips;
gint n_mode_groups;
ClutterInputDeviceMapping mapping_mode;
guint has_cursor : 1;
guint is_enabled : 1;
};
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);
gint (* get_group_n_modes) (ClutterInputDevice *device,
gint group);
gboolean (* is_grouped) (ClutterInputDevice *device,
ClutterInputDevice *other_device);
/* Keyboard accessbility */
void (* process_kbd_a11y_event) (ClutterEvent *event,
ClutterInputDevice *device,
ClutterEmitInputDeviceEvent emit_event_func);
};
/* Platform-dependent interface */
typedef struct _ClutterEventExtender ClutterEventExtender;
typedef struct _ClutterEventExtenderInterface ClutterEventExtenderInterface;
#define CLUTTER_TYPE_EVENT_EXTENDER (clutter_event_extender_get_type ())
#define CLUTTER_EVENT_EXTENDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CLUTTER_TYPE_EVENT_EXTENDER, ClutterEventExtender))
#define CLUTTER_IS_EVENT_EXTENDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CLUTTER_TYPE_EVENT_EXTENDER))
#define CLUTTER_EVENT_EXTENDER_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), CLUTTER_TYPE_EVENT_EXTENDER, ClutterEventExtenderInterface))
struct _ClutterEventExtenderInterface
{
GTypeInterface g_iface;
void (* copy_event_data) (ClutterEventExtender *event_extender,
const ClutterEvent *src,
ClutterEvent *dest);
void (* free_event_data) (ClutterEventExtender *event_extender,
ClutterEvent *event);
};
GType clutter_event_extender_get_type (void) G_GNUC_CONST;
/* device manager */
void _clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device);
void _clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device);
void _clutter_device_manager_update_devices (ClutterDeviceManager *device_manager);
void _clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager,
ClutterStage *stage);
ClutterBackend *_clutter_device_manager_get_backend (ClutterDeviceManager *device_manager);
void _clutter_device_manager_compress_motion (ClutterDeviceManager *device_manger,
ClutterEvent *event,
const ClutterEvent *to_discard);
/* input device */
gboolean _clutter_input_device_has_sequence (ClutterInputDevice *device,
ClutterEventSequence *sequence);
void _clutter_input_device_add_event_sequence (ClutterInputDevice *device,
ClutterEvent *event);
void _clutter_input_device_remove_event_sequence (ClutterInputDevice *device,
ClutterEvent *event);
void _clutter_input_device_set_coords (ClutterInputDevice *device,
ClutterEventSequence *sequence,
gfloat x,
gfloat y,
ClutterStage *stage);
void _clutter_input_device_set_state (ClutterInputDevice *device,
ClutterModifierType state);
void _clutter_input_device_set_time (ClutterInputDevice *device,
guint32 time_);
void _clutter_input_device_set_stage (ClutterInputDevice *device,
ClutterStage *stage);
ClutterStage * _clutter_input_device_get_stage (ClutterInputDevice *device);
void _clutter_input_device_set_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence,
ClutterActor *actor,
gboolean emit_crossing);
ClutterActor * _clutter_input_device_update (ClutterInputDevice *device,
ClutterEventSequence *sequence,
gboolean emit_crossing);
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
guint n_keys);
guint _clutter_input_device_add_axis (ClutterInputDevice *device,
ClutterInputAxis axis,
gdouble min_value,
gdouble max_value,
gdouble resolution);
void _clutter_input_device_reset_axes (ClutterInputDevice *device);
void _clutter_input_device_set_associated_device (ClutterInputDevice *device,
ClutterInputDevice *associated);
void _clutter_input_device_add_slave (ClutterInputDevice *master,
ClutterInputDevice *slave);
void _clutter_input_device_remove_slave (ClutterInputDevice *master,
ClutterInputDevice *slave);
gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device,
guint index_,
gdouble value,
gdouble *axis_value);
void _clutter_input_device_add_scroll_info (ClutterInputDevice *device,
guint index_,
ClutterScrollDirection direction,
gdouble increment);
void _clutter_input_device_reset_scroll_info (ClutterInputDevice *device);
gboolean _clutter_input_device_get_scroll_delta (ClutterInputDevice *device,
guint index_,
gdouble value,
ClutterScrollDirection *direction_p,
gdouble *delta_p);
ClutterInputDeviceTool * clutter_input_device_lookup_tool (ClutterInputDevice *device,
guint64 serial,
ClutterInputDeviceToolType type);
void clutter_input_device_add_tool (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
void clutter_input_device_update_from_tool (ClutterInputDevice *device,
ClutterInputDeviceTool *tool);
G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_PRIVATE_H__ */

View File

@ -0,0 +1,587 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* SECTION:clutter-device-manager
* @short_description: Maintains the list of input devices
*
* #ClutterDeviceManager is a singleton object, owned by Clutter, which
* maintains the list of #ClutterInputDevice<!-- -->s.
*
* Depending on the backend used by Clutter it is possible to use the
* #ClutterDeviceManager::device-added and
* #ClutterDeviceManager::device-removed to monitor addition and removal
* of devices.
*
* #ClutterDeviceManager is available since Clutter 1.2
*/
#include "clutter-build-config.h"
#include "clutter-backend-private.h"
#include "clutter-debug.h"
#include "clutter-device-manager-private.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-virtual-input-device.h"
#include "clutter-input-device-tool.h"
struct _ClutterDeviceManagerPrivate
{
/* back-pointer to the backend */
ClutterBackend *backend;
/* Keyboard a11y */
ClutterKbdA11ySettings kbd_a11y_settings;
};
enum
{
PROP_0,
PROP_BACKEND,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
enum
{
DEVICE_ADDED,
DEVICE_REMOVED,
TOOL_CHANGED,
KBD_A11Y_MASK_CHANGED,
KBD_A11Y_FLAGS_CHANGED,
LAST_SIGNAL
};
static guint manager_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterDeviceManager,
clutter_device_manager,
G_TYPE_OBJECT)
G_DEFINE_INTERFACE (ClutterEventExtender,
clutter_event_extender,
CLUTTER_TYPE_DEVICE_MANAGER)
static void
clutter_event_extender_default_init (ClutterEventExtenderInterface *iface)
{
}
static void
clutter_device_manager_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterDeviceManagerPrivate *priv = CLUTTER_DEVICE_MANAGER (gobject)->priv;
switch (prop_id)
{
case PROP_BACKEND:
priv->backend = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
clutter_device_manager_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterDeviceManagerPrivate *priv = CLUTTER_DEVICE_MANAGER (gobject)->priv;
switch (prop_id)
{
case PROP_BACKEND:
g_value_set_object (value, priv->backend);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
clutter_device_manager_class_init (ClutterDeviceManagerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
obj_props[PROP_BACKEND] =
g_param_spec_object ("backend",
P_("Backend"),
P_("The ClutterBackend of the device manager"),
CLUTTER_TYPE_BACKEND,
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
gobject_class->set_property = clutter_device_manager_set_property;
gobject_class->get_property = clutter_device_manager_get_property;
g_object_class_install_properties (gobject_class,
PROP_LAST,
obj_props);
/**
* ClutterDeviceManager::device-added:
* @manager: the #ClutterDeviceManager that emitted the signal
* @device: the newly added #ClutterInputDevice
*
* The ::device-added signal is emitted each time a device has been
* added to the #ClutterDeviceManager
*
* Since: 1.2
*/
manager_signals[DEVICE_ADDED] =
g_signal_new (I_("device-added"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_INPUT_DEVICE);
/**
* ClutterDeviceManager::device-removed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @device: the removed #ClutterInputDevice
*
* The ::device-removed signal is emitted each time a device has been
* removed from the #ClutterDeviceManager
*
* Since: 1.2
*/
manager_signals[DEVICE_REMOVED] =
g_signal_new (I_("device-removed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_INPUT_DEVICE);
manager_signals[TOOL_CHANGED] =
g_signal_new (I_("tool-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__OBJECT_OBJECT,
G_TYPE_NONE, 2,
CLUTTER_TYPE_INPUT_DEVICE,
CLUTTER_TYPE_INPUT_DEVICE_TOOL);
/**
* ClutterDeviceManager::kbd-a11y-mods-state-changed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @latched_mask: the latched modifier mask from stickykeys
* @locked_mask: the locked modifier mask from stickykeys
*
* The ::kbd-a11y-mods-state-changed signal is emitted each time either the
* latched modifiers mask or locked modifiers mask are changed as the
* result of keyboard accessibilty's sticky keys operations.
*/
manager_signals[KBD_A11Y_MASK_CHANGED] =
g_signal_new (I_("kbd-a11y-mods-state-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__UINT_UINT,
G_TYPE_NONE, 2,
G_TYPE_UINT,
G_TYPE_UINT);
/**
* ClutterDeviceManager::kbd-a11y-flags-changed:
* @manager: the #ClutterDeviceManager that emitted the signal
* @settings_flags: the new ClutterKeyboardA11yFlags configuration
* @changed_mask: the ClutterKeyboardA11yFlags changed
*
* The ::kbd-a11y-flags-changed signal is emitted each time the
* ClutterKeyboardA11yFlags configuration is changed as the result of
* keyboard accessibilty operations.
*/
manager_signals[KBD_A11Y_FLAGS_CHANGED] =
g_signal_new (I_("kbd-a11y-flags-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
_clutter_marshal_VOID__UINT_UINT,
G_TYPE_NONE, 2,
G_TYPE_UINT,
G_TYPE_UINT);
}
static void
clutter_device_manager_init (ClutterDeviceManager *self)
{
self->priv = clutter_device_manager_get_instance_private (self);
}
/**
* clutter_device_manager_get_default:
*
* Retrieves the device manager singleton
*
* Return value: (transfer none): the #ClutterDeviceManager singleton.
* The returned instance is owned by Clutter and it should not be
* modified or freed
*
* Since: 1.2
*/
ClutterDeviceManager *
clutter_device_manager_get_default (void)
{
ClutterBackend *backend = clutter_get_default_backend ();
return backend->device_manager;
}
/**
* clutter_device_manager_list_devices:
* @device_manager: a #ClutterDeviceManager
*
* Lists all currently registered input devices
*
* Return value: (transfer container) (element-type Clutter.InputDevice):
* a newly allocated list of #ClutterInputDevice objects. Use
* g_slist_free() to deallocate it when done
*
* Since: 1.2
*/
GSList *
clutter_device_manager_list_devices (ClutterDeviceManager *device_manager)
{
const GSList *devices;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
devices = clutter_device_manager_peek_devices (device_manager);
return g_slist_copy ((GSList *) devices);
}
/**
* clutter_device_manager_peek_devices:
* @device_manager: a #ClutterDeviceManager
*
* Lists all currently registered input devices
*
* Return value: (transfer none) (element-type Clutter.InputDevice):
* a pointer to the internal list of #ClutterInputDevice objects. The
* returned list is owned by the #ClutterDeviceManager and should never
* be modified or freed
*
* Since: 1.2
*/
const GSList *
clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_devices (device_manager);
}
/**
* clutter_device_manager_get_device:
* @device_manager: a #ClutterDeviceManager
* @device_id: the integer id of a device
*
* Retrieves the #ClutterInputDevice with the given @device_id
*
* Return value: (transfer none): a #ClutterInputDevice or %NULL. The
* returned device is owned by the #ClutterDeviceManager and should
* never be modified or freed
*
* Since: 1.2
*/
ClutterInputDevice *
clutter_device_manager_get_device (ClutterDeviceManager *device_manager,
gint device_id)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_device (device_manager, device_id);
}
/**
* clutter_device_manager_get_core_device:
* @device_manager: a #ClutterDeviceManager
* @device_type: the type of the core device
*
* Retrieves the core #ClutterInputDevice of type @device_type
*
* Core devices are devices created automatically by the default
* Clutter backend
*
* Return value: (transfer none): a #ClutterInputDevice or %NULL. The
* returned device is owned by the #ClutterDeviceManager and should
* not be modified or freed
*
* Since: 1.2
*/
ClutterInputDevice *
clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_core_device (device_manager, device_type);
}
void
_clutter_device_manager_select_stage_events (ClutterDeviceManager *device_manager,
ClutterStage *stage)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
if (manager_class->select_stage_events)
manager_class->select_stage_events (device_manager, stage);
}
/*
* _clutter_device_manager_add_device:
* @device_manager: a #ClutterDeviceManager
* @device: a #ClutterInputDevice
*
* Adds @device to the list of #ClutterInputDevice<!-- -->s maintained
* by @device_manager
*
* The reference count of @device is not increased
*
* The #ClutterDeviceManager::device-added signal is emitted after
* adding @device to the list
*/
void
_clutter_device_manager_add_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
g_assert (manager_class->add_device != NULL);
manager_class->add_device (device_manager, device);
g_signal_emit (device_manager, manager_signals[DEVICE_ADDED], 0, device);
}
/*
* _clutter_device_manager_remove_device:
* @device_manager: a #ClutterDeviceManager
* @device: a #ClutterInputDevice
*
* Removes @device from the list of #ClutterInputDevice<!-- -->s
* maintained by @device_manager
*
* The reference count of @device is not decreased
*
* The #ClutterDeviceManager::device-removed signal is emitted after
* removing @device from the list
*/
void
_clutter_device_manager_remove_device (ClutterDeviceManager *device_manager,
ClutterInputDevice *device)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
g_assert (manager_class->remove_device != NULL);
/* The subclass remove_device() method will likely unref it but we
have to keep it alive during the signal emission. */
g_object_ref (device);
manager_class->remove_device (device_manager, device);
g_signal_emit (device_manager, manager_signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
}
/*
* _clutter_device_manager_update_devices:
* @device_manager: a #ClutterDeviceManager
*
* Updates every #ClutterInputDevice handled by @device_manager
* by performing a pick paint at the coordinates of each pointer
* device
*/
void
_clutter_device_manager_update_devices (ClutterDeviceManager *device_manager)
{
const GSList *d;
for (d = clutter_device_manager_peek_devices (device_manager);
d != NULL;
d = d->next)
{
ClutterInputDevice *device = d->data;
ClutterInputDeviceType device_type;
/* we only care about pointer devices */
device_type = clutter_input_device_get_device_type (device);
if (device_type != CLUTTER_POINTER_DEVICE)
continue;
/* out of stage */
if (device->stage == NULL)
continue;
/* the user disabled motion events delivery on actors for
* the stage the device is on; we don't perform any picking
* since the source of the events will always be set to be
* the stage
*/
if (!clutter_stage_get_motion_events_enabled (device->stage))
continue;
_clutter_input_device_update (device, NULL, TRUE);
}
}
ClutterBackend *
_clutter_device_manager_get_backend (ClutterDeviceManager *manager)
{
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (manager), NULL);
return manager->priv->backend;
}
/**
* clutter_device_manager_create_virtual_device:
* @device_manager: a #ClutterDeviceManager
* @device_type: the type of the virtual device
*
* Creates a virtual input device.
*
* Returns: (transfer full): a newly created virtual device
**/
ClutterVirtualInputDevice *
clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->create_virtual_device (device_manager,
device_type);
}
/**
* clutter_device_manager_supported_virtua_device_types: (skip)
*/
ClutterVirtualDeviceType
clutter_device_manager_get_supported_virtual_device_types (ClutterDeviceManager *device_manager)
{
ClutterDeviceManagerClass *manager_class;
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager),
CLUTTER_VIRTUAL_DEVICE_TYPE_NONE);
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
return manager_class->get_supported_virtual_device_types (device_manager);
}
void
_clutter_device_manager_compress_motion (ClutterDeviceManager *device_manager,
ClutterEvent *event,
const ClutterEvent *to_discard)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
if (!manager_class->compress_motion)
return;
manager_class->compress_motion (device_manager, event, to_discard);
}
static gboolean
are_kbd_a11y_settings_equal (ClutterKbdA11ySettings *a,
ClutterKbdA11ySettings *b)
{
return (a->controls == b->controls &&
a->slowkeys_delay == b->slowkeys_delay &&
a->debounce_delay == b->debounce_delay &&
a->timeout_delay == b->timeout_delay &&
a->mousekeys_init_delay == b->mousekeys_init_delay &&
a->mousekeys_max_speed == b->mousekeys_max_speed &&
a->mousekeys_accel_time == b->mousekeys_accel_time);
}
void
clutter_device_manager_set_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings)
{
ClutterDeviceManagerClass *manager_class;
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
if (are_kbd_a11y_settings_equal (&device_manager->priv->kbd_a11y_settings, settings))
return;
device_manager->priv->kbd_a11y_settings = *settings;
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
if (manager_class->apply_kbd_a11y_settings)
manager_class->apply_kbd_a11y_settings (device_manager, settings);
}
void
clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings)
{
g_return_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager));
*settings = device_manager->priv->kbd_a11y_settings;
}

View File

@ -0,0 +1,161 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author: Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DEVICE_MANAGER_H__
#define __CLUTTER_DEVICE_MANAGER_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <clutter/clutter-input-device.h>
#include <clutter/clutter-stage.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DEVICE_MANAGER (clutter_device_manager_get_type ())
#define CLUTTER_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManager))
#define CLUTTER_IS_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER))
#define CLUTTER_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManagerClass))
#define CLUTTER_IS_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER))
#define CLUTTER_DEVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER, ClutterDeviceManagerClass))
typedef struct _ClutterDeviceManager ClutterDeviceManager;
typedef struct _ClutterDeviceManagerPrivate ClutterDeviceManagerPrivate;
typedef struct _ClutterDeviceManagerClass ClutterDeviceManagerClass;
/**
* ClutterVirtualDeviceType:
*/
typedef enum _ClutterVirtualDeviceType
{
CLUTTER_VIRTUAL_DEVICE_TYPE_NONE = 0,
CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD = 1 << 0,
CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER = 1 << 1,
CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN = 1 << 2,
} ClutterVirtualDeviceType;
/**
* ClutterKbdA11ySettings:
*
* The #ClutterKbdA11ySettings structure contains keyboard accessibility
* settings
*
*/
typedef struct _ClutterKbdA11ySettings
{
ClutterKeyboardA11yFlags controls;
gint slowkeys_delay;
gint debounce_delay;
gint timeout_delay;
gint mousekeys_init_delay;
gint mousekeys_max_speed;
gint mousekeys_accel_time;
} ClutterKbdA11ySettings;
/**
* ClutterDeviceManager:
*
* The #ClutterDeviceManager structure contains only private data
*
* Since: 1.2
*/
struct _ClutterDeviceManager
{
/*< private >*/
GObject parent_instance;
ClutterDeviceManagerPrivate *priv;
};
/**
* ClutterDeviceManagerClass:
*
* The #ClutterDeviceManagerClass structure contains only private data
*
* Since: 1.2
*/
struct _ClutterDeviceManagerClass
{
/*< private >*/
GObjectClass parent_class;
const GSList * (* get_devices) (ClutterDeviceManager *device_manager);
ClutterInputDevice *(* get_core_device) (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
ClutterInputDevice *(* get_device) (ClutterDeviceManager *device_manager,
gint device_id);
void (* add_device) (ClutterDeviceManager *manager,
ClutterInputDevice *device);
void (* remove_device) (ClutterDeviceManager *manager,
ClutterInputDevice *device);
void (* select_stage_events) (ClutterDeviceManager *manager,
ClutterStage *stage);
ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
ClutterVirtualDeviceType (* get_supported_virtual_device_types) (ClutterDeviceManager *device_manager);
void (* compress_motion) (ClutterDeviceManager *device_manger,
ClutterEvent *event,
const ClutterEvent *to_discard);
/* Keyboard accessbility */
void (* apply_kbd_a11y_settings) (ClutterDeviceManager *device_manger,
ClutterKbdA11ySettings *settings);
/* padding */
gpointer _padding[6];
};
CLUTTER_EXPORT
GType clutter_device_manager_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterDeviceManager *clutter_device_manager_get_default (void);
CLUTTER_EXPORT
GSList * clutter_device_manager_list_devices (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
const GSList * clutter_device_manager_peek_devices (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
ClutterInputDevice * clutter_device_manager_get_device (ClutterDeviceManager *device_manager,
gint device_id);
CLUTTER_EXPORT
ClutterInputDevice * clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
CLUTTER_EXPORT
ClutterVirtualInputDevice *clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager,
ClutterInputDeviceType device_type);
CLUTTER_EXPORT
ClutterVirtualDeviceType clutter_device_manager_get_supported_virtual_device_types (ClutterDeviceManager *device_manager);
CLUTTER_EXPORT
void clutter_device_manager_set_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings);
CLUTTER_EXPORT
void clutter_device_manager_get_kbd_a11y_settings (ClutterDeviceManager *device_manager,
ClutterKbdA11ySettings *settings);
G_END_DECLS
#endif /* __CLUTTER_DEVICE_MANAGER_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DRAG_ACTION_H__
#define __CLUTTER_DRAG_ACTION_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <clutter/clutter-action.h>
#include <clutter/clutter-event.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DRAG_ACTION (clutter_drag_action_get_type ())
#define CLUTTER_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragAction))
#define CLUTTER_IS_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DRAG_ACTION))
#define CLUTTER_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass))
#define CLUTTER_IS_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DRAG_ACTION))
#define CLUTTER_DRAG_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass))
typedef struct _ClutterDragAction ClutterDragAction;
typedef struct _ClutterDragActionPrivate ClutterDragActionPrivate;
typedef struct _ClutterDragActionClass ClutterDragActionClass;
/**
* ClutterDragAction:
*
* The #ClutterDragAction structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterDragAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterDragActionPrivate *priv;
};
/**
* ClutterDragActionClass:
* @drag_begin: class handler of the #ClutterDragAction::drag-begin signal
* @drag_motion: class handler of the #ClutterDragAction::drag-motion signal
* @drag_end: class handler of the #ClutterDragAction::drag-end signal
* @drag_progress: class handler of the #ClutterDragAction::drag-progress signal
*
* The #ClutterDragActionClass structure contains
* only private data
*
* Since: 1.4
*/
struct _ClutterDragActionClass
{
/*< private >*/
ClutterActionClass parent_class;
/*< public >*/
void (* drag_begin) (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers);
void (* drag_motion) (ClutterDragAction *action,
ClutterActor *actor,
gfloat delta_x,
gfloat delta_y);
void (* drag_end) (ClutterDragAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y,
ClutterModifierType modifiers);
gboolean (* drag_progress) (ClutterDragAction *action,
ClutterActor *actor,
gfloat delta_x,
gfloat delta_y);
/*< private >*/
void (* _clutter_drag_action1) (void);
void (* _clutter_drag_action2) (void);
void (* _clutter_drag_action3) (void);
void (* _clutter_drag_action4) (void);
};
CLUTTER_EXPORT
GType clutter_drag_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_drag_action_new (void);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_threshold (ClutterDragAction *action,
gint x_threshold,
gint y_threshold);
CLUTTER_EXPORT
void clutter_drag_action_get_drag_threshold (ClutterDragAction *action,
guint *x_threshold,
guint *y_threshold);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_handle (ClutterDragAction *action,
ClutterActor *handle);
CLUTTER_EXPORT
ClutterActor * clutter_drag_action_get_drag_handle (ClutterDragAction *action);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_axis (ClutterDragAction *action,
ClutterDragAxis axis);
CLUTTER_EXPORT
ClutterDragAxis clutter_drag_action_get_drag_axis (ClutterDragAction *action);
CLUTTER_EXPORT
void clutter_drag_action_get_press_coords (ClutterDragAction *action,
gfloat *press_x,
gfloat *press_y);
CLUTTER_EXPORT
void clutter_drag_action_get_motion_coords (ClutterDragAction *action,
gfloat *motion_x,
gfloat *motion_y);
CLUTTER_EXPORT
gboolean clutter_drag_action_get_drag_area (ClutterDragAction *action,
ClutterRect *drag_area);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_area (ClutterDragAction *action,
const ClutterRect *drag_area);
G_END_DECLS
#endif /* __CLUTTER_DRAG_ACTION_H__ */

View File

@ -0,0 +1,531 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
/**
* SECTION:clutter-drop-action
* @Title: ClutterDropAction
* @short_description: An action for drop targets
*
* #ClutterDropAction is a #ClutterAction that allows a #ClutterActor
* implementation to control what happens when an actor dragged using
* a #ClutterDragAction crosses the target area or when a dragged actor
* is released (or "dropped") on the target area.
*
* A trivial use of #ClutterDropAction consists in connecting to the
* #ClutterDropAction::drop signal and handling the drop from there,
* for instance:
*
* |[<!-- language="C" -->
* ClutterAction *action = clutter_drop_action ();
*
* g_signal_connect (action, "drop", G_CALLBACK (on_drop), NULL);
* clutter_actor_add_action (an_actor, action);
* ]|
*
* The #ClutterDropAction::can-drop can be used to control whether the
* #ClutterDropAction::drop signal is going to be emitted; returning %FALSE
* from a handler connected to the #ClutterDropAction::can-drop signal will
* cause the #ClutterDropAction::drop signal to be skipped when the input
* device button is released.
*
* It's important to note that #ClutterDropAction will only work with
* actors dragged using #ClutterDragAction.
*
* See [drop-action.c](https://git.gnome.org/browse/clutter/tree/examples/drop-action.c?h=clutter-1.18)
* for an example of how to use #ClutterDropAction.
*
* #ClutterDropAction is available since Clutter 1.8
*/
#include "clutter-build-config.h"
#include "clutter-drop-action.h"
#include "clutter-actor-meta-private.h"
#include "clutter-actor-private.h"
#include "clutter-drag-action.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-stage-private.h"
struct _ClutterDropActionPrivate
{
ClutterActor *actor;
ClutterActor *stage;
gulong mapped_id;
};
typedef struct _DropTarget {
ClutterActor *stage;
gulong capture_id;
GHashTable *actions;
ClutterDropAction *last_action;
} DropTarget;
enum
{
CAN_DROP,
OVER_IN,
OVER_OUT,
DROP,
DROP_CANCEL,
LAST_SIGNAL
};
static guint drop_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterDropAction, clutter_drop_action, CLUTTER_TYPE_ACTION)
static void
drop_target_free (gpointer _data)
{
DropTarget *data = _data;
g_signal_handler_disconnect (data->stage, data->capture_id);
g_hash_table_destroy (data->actions);
g_free (data);
}
static gboolean
on_stage_capture (ClutterStage *stage,
ClutterEvent *event,
gpointer user_data)
{
DropTarget *data = user_data;
gfloat event_x, event_y;
ClutterActor *actor, *drag_actor;
ClutterDropAction *drop_action;
ClutterInputDevice *device;
gboolean was_reactive;
switch (clutter_event_type (event))
{
case CLUTTER_MOTION:
case CLUTTER_BUTTON_RELEASE:
if (clutter_event_type (event) == CLUTTER_MOTION &&
!(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK))
return CLUTTER_EVENT_PROPAGATE;
if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE &&
clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY)
return CLUTTER_EVENT_PROPAGATE;
device = clutter_event_get_device (event);
drag_actor = _clutter_stage_get_pointer_drag_actor (stage, device);
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
break;
case CLUTTER_TOUCH_UPDATE:
case CLUTTER_TOUCH_END:
drag_actor = _clutter_stage_get_touch_drag_actor (stage,
clutter_event_get_event_sequence (event));
if (drag_actor == NULL)
return CLUTTER_EVENT_PROPAGATE;
break;
default:
return CLUTTER_EVENT_PROPAGATE;
}
clutter_event_get_coords (event, &event_x, &event_y);
/* get the actor under the cursor, excluding the dragged actor; we
* use reactivity because it won't cause any scene invalidation
*/
was_reactive = clutter_actor_get_reactive (drag_actor);
clutter_actor_set_reactive (drag_actor, FALSE);
actor = clutter_stage_get_actor_at_pos (stage, CLUTTER_PICK_REACTIVE,
event_x,
event_y);
if (actor == NULL || actor == CLUTTER_ACTOR (stage))
{
if (data->last_action != NULL)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action);
g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0,
clutter_actor_meta_get_actor (meta));
data->last_action = NULL;
}
goto out;
}
drop_action = g_hash_table_lookup (data->actions, actor);
if (drop_action == NULL)
{
if (data->last_action != NULL)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action);
g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0,
clutter_actor_meta_get_actor (meta));
data->last_action = NULL;
}
goto out;
}
else
{
if (data->last_action != drop_action)
{
ClutterActorMeta *meta;
if (data->last_action != NULL)
{
meta = CLUTTER_ACTOR_META (data->last_action);
g_signal_emit (data->last_action, drop_signals[OVER_OUT], 0,
clutter_actor_meta_get_actor (meta));
}
meta = CLUTTER_ACTOR_META (drop_action);
g_signal_emit (drop_action, drop_signals[OVER_IN], 0,
clutter_actor_meta_get_actor (meta));
}
data->last_action = drop_action;
}
out:
if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE ||
clutter_event_type (event) == CLUTTER_TOUCH_END)
{
if (data->last_action != NULL)
{
ClutterActorMeta *meta = CLUTTER_ACTOR_META (data->last_action);
gboolean can_drop = FALSE;
g_signal_emit (data->last_action, drop_signals[CAN_DROP], 0,
clutter_actor_meta_get_actor (meta),
event_x, event_y,
&can_drop);
if (can_drop)
{
g_signal_emit (data->last_action, drop_signals[DROP], 0,
clutter_actor_meta_get_actor (meta),
event_x, event_y);
}
else
{
g_signal_emit (data->last_action, drop_signals[DROP_CANCEL], 0,
clutter_actor_meta_get_actor (meta),
event_x, event_y);
}
}
data->last_action = NULL;
}
if (drag_actor != NULL)
clutter_actor_set_reactive (drag_actor, was_reactive);
return CLUTTER_EVENT_PROPAGATE;
}
static void
drop_action_register (ClutterDropAction *self)
{
ClutterDropActionPrivate *priv = self->priv;
DropTarget *data;
g_assert (priv->stage != NULL);
data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets");
if (data == NULL)
{
data = g_new0 (DropTarget, 1);
data->stage = priv->stage;
data->actions = g_hash_table_new (NULL, NULL);
data->capture_id = g_signal_connect (priv->stage, "captured-event",
G_CALLBACK (on_stage_capture),
data);
g_object_set_data_full (G_OBJECT (priv->stage), "__clutter_drop_targets",
data,
drop_target_free);
}
g_hash_table_replace (data->actions, priv->actor, self);
}
static void
drop_action_unregister (ClutterDropAction *self)
{
ClutterDropActionPrivate *priv = self->priv;
DropTarget *data = NULL;
if (priv->stage != NULL)
data = g_object_get_data (G_OBJECT (priv->stage), "__clutter_drop_targets");
if (data == NULL)
return;
g_hash_table_remove (data->actions, priv->actor);
if (g_hash_table_size (data->actions) == 0)
g_object_set_data (G_OBJECT (data->stage), "__clutter_drop_targets", NULL);
}
static void
on_actor_mapped (ClutterActor *actor,
GParamSpec *pspec,
ClutterDropAction *self)
{
if (clutter_actor_is_mapped (actor))
{
if (self->priv->stage == NULL)
self->priv->stage = clutter_actor_get_stage (actor);
drop_action_register (self);
}
else
drop_action_unregister (self);
}
static void
clutter_drop_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterDropActionPrivate *priv = CLUTTER_DROP_ACTION (meta)->priv;
if (priv->actor != NULL)
{
drop_action_unregister (CLUTTER_DROP_ACTION (meta));
if (priv->mapped_id != 0)
g_signal_handler_disconnect (priv->actor, priv->mapped_id);
priv->stage = NULL;
priv->actor = NULL;
priv->mapped_id = 0;
}
priv->actor = actor;
if (priv->actor != NULL)
{
priv->stage = clutter_actor_get_stage (actor);
priv->mapped_id = g_signal_connect (actor, "notify::mapped",
G_CALLBACK (on_actor_mapped),
meta);
if (priv->stage != NULL)
drop_action_register (CLUTTER_DROP_ACTION (meta));
}
CLUTTER_ACTOR_META_CLASS (clutter_drop_action_parent_class)->set_actor (meta, actor);
}
static gboolean
signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer user_data)
{
gboolean continue_emission;
continue_emission = g_value_get_boolean (handler_return);
g_value_set_boolean (return_accu, continue_emission);
return continue_emission;
}
static gboolean
clutter_drop_action_real_can_drop (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y)
{
return TRUE;
}
static void
clutter_drop_action_class_init (ClutterDropActionClass *klass)
{
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
meta_class->set_actor = clutter_drop_action_set_actor;
klass->can_drop = clutter_drop_action_real_can_drop;
/**
* ClutterDropAction::can-drop:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @event_x: the X coordinate (in stage space) of the drop event
* @event_y: the Y coordinate (in stage space) of the drop event
*
* The ::can-drop signal is emitted when the dragged actor is dropped
* on @actor. The return value of the ::can-drop signal will determine
* whether or not the #ClutterDropAction::drop signal is going to be
* emitted on @action.
*
* The default implementation of #ClutterDropAction returns %TRUE for
* this signal.
*
* Return value: %TRUE if the drop is accepted, and %FALSE otherwise
*
* Since: 1.8
*/
drop_signals[CAN_DROP] =
g_signal_new (I_("can-drop"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, can_drop),
signal_accumulator, NULL,
_clutter_marshal_BOOLEAN__OBJECT_FLOAT_FLOAT,
G_TYPE_BOOLEAN, 3,
CLUTTER_TYPE_ACTOR,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
/**
* ClutterDropAction::over-in:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
*
* The ::over-in signal is emitted when the dragged actor crosses
* into @actor.
*
* Since: 1.8
*/
drop_signals[OVER_IN] =
g_signal_new (I_("over-in"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, over_in),
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
/**
* ClutterDropAction::over-out:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
*
* The ::over-out signal is emitted when the dragged actor crosses
* outside @actor.
*
* Since: 1.8
*/
drop_signals[OVER_OUT] =
g_signal_new (I_("over-out"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, over_out),
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
/**
* ClutterDropAction::drop:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @event_x: the X coordinate (in stage space) of the drop event
* @event_y: the Y coordinate (in stage space) of the drop event
*
* The ::drop signal is emitted when the dragged actor is dropped
* on @actor. This signal is only emitted if at least an handler of
* #ClutterDropAction::can-drop returns %TRUE.
*
* Since: 1.8
*/
drop_signals[DROP] =
g_signal_new (I_("drop"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, drop),
NULL, NULL,
_clutter_marshal_VOID__OBJECT_FLOAT_FLOAT,
G_TYPE_NONE, 3,
CLUTTER_TYPE_ACTOR,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
/**
* ClutterDropAction::drop-cancel:
* @action: the #ClutterDropAction that emitted the signal
* @actor: the #ClutterActor attached to the @action
* @event_x: the X coordinate (in stage space) of the drop event
* @event_y: the Y coordinate (in stage space) of the drop event
*
* The ::drop-cancel signal is emitted when the drop is refused
* by an emission of the #ClutterDropAction::can-drop signal.
*
* After the ::drop-cancel signal is fired the active drag is
* terminated.
*
* Since: 1.12
*/
drop_signals[DROP_CANCEL] =
g_signal_new (I_("drop-cancel"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterDropActionClass, drop),
NULL, NULL,
_clutter_marshal_VOID__OBJECT_FLOAT_FLOAT,
G_TYPE_NONE, 3,
CLUTTER_TYPE_ACTOR,
G_TYPE_FLOAT,
G_TYPE_FLOAT);
}
static void
clutter_drop_action_init (ClutterDropAction *self)
{
self->priv = clutter_drop_action_get_instance_private (self);
}
/**
* clutter_drop_action_new:
*
* Creates a new #ClutterDropAction.
*
* Use clutter_actor_add_action() to add the action to a #ClutterActor.
*
* Return value: the newly created #ClutterDropAction
*
* Since: 1.8
*/
ClutterAction *
clutter_drop_action_new (void)
{
return g_object_new (CLUTTER_TYPE_DROP_ACTION, NULL);
}

View File

@ -0,0 +1,115 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#ifndef __CLUTTER_DROP_ACTION_H__
#define __CLUTTER_DROP_ACTION_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be directly included."
#endif
#include <clutter/clutter-action.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_DROP_ACTION (clutter_drop_action_get_type ())
#define CLUTTER_DROP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropAction))
#define CLUTTER_IS_DROP_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DROP_ACTION))
#define CLUTTER_DROP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass))
#define CLUTTER_IS_DROP_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DROP_ACTION))
#define CLUTTER_DROP_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DROP_ACTION, ClutterDropActionClass))
typedef struct _ClutterDropAction ClutterDropAction;
typedef struct _ClutterDropActionPrivate ClutterDropActionPrivate;
typedef struct _ClutterDropActionClass ClutterDropActionClass;
/**
* ClutterDropAction:
*
* The #ClutterDropAction structure contains only
* private data and should be accessed using the provided API.
*
* Since: 1.8
*/
struct _ClutterDropAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterDropActionPrivate *priv;
};
/**
* ClutterDropActionClass:
* @can_drop: class handler for the #ClutterDropAction::can-drop signal
* @over_in: class handler for the #ClutterDropAction::over-in signal
* @over_out: class handler for the #ClutterDropAction::over-out signal
* @drop: class handler for the #ClutterDropAction::drop signal
*
* The #ClutterDropActionClass structure contains
* only private data.
*
* Since: 1.8
*/
struct _ClutterDropActionClass
{
/*< private >*/
ClutterActionClass parent_class;
/*< public >*/
gboolean (* can_drop) (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y);
void (* over_in) (ClutterDropAction *action,
ClutterActor *actor);
void (* over_out) (ClutterDropAction *action,
ClutterActor *actor);
void (* drop) (ClutterDropAction *action,
ClutterActor *actor,
gfloat event_x,
gfloat event_y);
/*< private >*/
void (*_clutter_drop_action1) (void);
void (*_clutter_drop_action2) (void);
void (*_clutter_drop_action3) (void);
void (*_clutter_drop_action4) (void);
void (*_clutter_drop_action5) (void);
void (*_clutter_drop_action6) (void);
void (*_clutter_drop_action7) (void);
void (*_clutter_drop_action8) (void);
};
CLUTTER_EXPORT
GType clutter_drop_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterAction * clutter_drop_action_new (void);
G_END_DECLS
#endif /* __CLUTTER_DROP_ACTION_H__ */

Some files were not shown because too many files have changed in this diff Show More