Compare commits

..

36 Commits

Author SHA1 Message Date
Jonas Ådahl
9b2ee14eb1 tests/stacking: Add test checking the initial size
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
0a8286e008 tests/stacking: Add test for checking restored positions
Going maximized -> unmaximized should restore the previous position. The
same for untiling, or going from tiled, to maximized, to floating.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
42fecdb60b tests/test-runner: Add 'move' and 'assert_position'
Make it possible for tests to move the windows, and check their
positions.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
f84ec95d2f tests/restore-size: Also test that untiling restores correctly
Tiling, then untiling should restore to the size prior to tiling.

Tiling, maximizing, then unmaximizing should also restore to the size
prior to tiling.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
4b4cf96de1 tests/test-runner: Add tile and untile commands
This allows test cases to tile windows to the right or left, and untile,
just as the keyboard shortcuts does.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
c413dd9078 window: Set fall-back tile monitor if not set
When tiling, we want to set the tile monitor. To not have to do this
from the call site, make meta_window_tile() fall back to the current
monitor if nothing set it prior to the call.

This will make it more convenient for test cases that what to test
tiling.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
95f3fe7bd5 window: Add meta_window_untile()
It does the same as the untile keyboard shortcut does, i.e. handles
going back to saved maximized state. It's split out to be able to be
tested by the stacking tests.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
443dd146e1 tests/stacking: Test some maximize fullscreen interaction
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
2d982b678e tests/test-client: Add 'fullscreen' and 'unfullscreen' commands
This needs some hand holding when calculating the "full" size of the
window, as the titlebar isn't actually shown.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
7cf61a392d tests/stacking: Check that unmaximize to new size works
A client that set a new fallback size while being maximized should not
restore to the one prior to being maximized.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
e190efb7af tests/stacking: Add test to verify we unmaximize correctly
The test tests that (for both X11 and Wayland) that:

 * The client unmaximizes after mapping maximized to a predictable size
 * That the client unmaximizes to the same size after toggling maximize

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
711adcb36e tests/test-runner: Add a 'wait_reconfigure' command
This makes sure that a client has properly responded to a configure
event it itself triggered. In practice, this is just two 'wait'
commands, with a 'dispatch' in between, which is needed because a single
one does not reliably include the two way round trip happening when e.g.
responding to a unmaximize configure event triggered by a unmaximize
request.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
b98ce96d09 tests/test-runner: Add 'assert_size' command
The 'assert_size' command checks that the size of the window, both
client side and compositor side, corresponds to an expected size set by
the test case.

The size comparison can only be done when the window is using 'csd', in
order for both the client and server to have the same amount of
understanding of the title bar. For ssd, the client cannot know how
large the title bar, thus cannot verify the full window size.

Sizes can be specified to mean the size of the monitor divided by a
number. This is that one can make sure a window is maximized or
fullscreened correctly.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
b7ad1fb086 tests/test-client: Remove shadow from X11 test client CSS style
Gtk is quite buggy and "fluid" in how it handles the shadow margins for
windows under X11. The "size" of the window fluctuate between including and
excluding a shadow margin in a way that causes issues, as there are no
atomic update of any state going on.

In order to avoid running into those particular issues now, lets get rid
of shadows so the margins are always zero, when the client is using the
X11 backend.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
d812cecc44 tests/test-client: Make 'resize' client command include the titlebar
To get some kind of consistency between what 'resize' means for the
compositor and the client, make the size correspond to the "frame rect"
of the window, i.e. the window geometry in the Wayland case, and the
window size including the titlebar in the X11 case.

This is so that the window size later can be reliably compared both in
the compositor and in the client using the same expected dimensions.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
965d74355a tests/test-client: Add line breaks to warning messages
When toying with the test client to try to reproduce issues (e.g.
writing commands on stdin to create and manipulate windows), when you
write a command incorrectly you'll get a warning printed to standard
out. The problem, however, is that it doesn't include a line break in
the end, meaning when you type the correct command, it won't be on a new
line.

Fix this minor annoyance by adding line breaks to all warning messages.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
92b1359d04 tests/test-runner: Plumb "resize" command
The test client could already understand the resize command, but they
could not be added to metatests as the command was not properly plumbed
via the test runner. Establish the plumbing for the resize command so
that resize tests can be added.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
c25fa19208 tests/test-client: Add commands to maximize/unmaximize
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Phillip Wood
ad500ef4e5 input-settings: fix device list iteration
Dereference the loop variable rather than the original list head. This
fixes a regression introduced in 4413b86a3 ("backends: Replace
ClutterDeviceManager usage in favor of ClutterSeat", 2019-10-04) which
broke button scrolling with trackballs.

Closes:https://gitlab.gnome.org/GNOME/mutter/-/issues/1120

(cherry picked from commit 3e967d731a)
2020-04-12 23:43:01 +02:00
Olivier Fourdan
9a2471db47 wayland: preserve xkb_state on VT switch
On VT switch, the devices are removed, which means for Wayland disabling
the keyboard.

When the keyboard is disabled, the associated `xkb_state` is freed and
recreated whenever the keyboard is re-enabled when switching back to the
compositor VT.

That means the `xkb_state` for Wayland is lost whereas the same for
clutter is kept, which causes to a discrepancy with locked modifiers on
VT switch.

To avoid that issue, preserve the XKB info only to dispose it when the
keyboard is eventually finalized.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/344
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1185


(cherry picked from commit 5b30a52bbd)
2020-04-08 14:04:02 +00:00
Carlos Garnacho
db164bcfa2 wayland/xdnd: Add error traps around Xdnd* IPC
Make all of them spew criticals, except for XdndLeave as it's feasible
to expect the window we are sending the event to did disappear in the
way (eg. if the window is destroyed while the DnD operation is ongoing
and the pointer is over the window).

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2590

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1184
2020-04-07 20:38:02 +02:00
Jonas Troeger
83553e3f6e backends/native: Translate coordinates of absolute motion events
The motion events of tablets for example need to be mapped on the
selected screen area if the input device is configured to use only a
part of the active logical monitor.
To achieve this behavior each motion event is transformed using the
transformation matrix set for the input device.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1118
2020-04-07 20:37:53 +02:00
Carlos Garnacho
3b2f6ae93d backends/x11: Fix access to WacomDevice
At some point we crossed the streams... In a short timespan we had
1f00aba92c merged, pushing WacomDevice to a common parent object,
and dcaa45fc0c implementing device grouping for X11.

The latter did not rely on the former, and just happened to
merge/compile without issues, but would promptly trigger a crash
whenever the API would be used.

Drop all traces of the WacomDevice internal to MetaInputDeviceX11.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1183


(cherry picked from commit f0718c7d95)
2020-04-07 17:48:09 +00:00
Jonas Dreßler
bc47f0a1ac clutter/stage: Don't assume stage relayouts reallocate everything
With the introduction of "shallow" relayouts, we are now able to enter
allocation cycles not only at the stage but also deeper down the
hierarchy if we know an actors allocation isn't affected by its children
since the NO_LAYOUT flag is set.

Now that means when queuing relayouts it's possible that
`priv->needs_allocation` gets set to TRUE for some actors down the
hierarchy, but not for actors higher up in the hierarchy. An actor tree
where that happens could look like that:

stage -> container -> container2 (NO_LAYOUT) -> textActor

With that tree, if the "textActor" queues a relayout, "container2" will
be added to the relayout hashtable of the stage and the actors "stage"
and "container" will have `priv->needs_allocation` set to FALSE.

Now if another relayout on the stage actor is queued,
`clutter_stage_queue_actor_relayout()` currently removes all the other
hashtable entries in favour of the stage entry, (wrongly) assuming that
will allocate everything. It doesn't allocate everything because in the
example above "container" has `priv->needs_allocation` set to FALSE,
which makes clutter_actor_allocate() return early before allocating its
children, so in the end "container2" will never get a new allocation.

To fix this, stop flushing the relayout hashtable when queuing a
stage-relayout and still add new entries to the hashtable if a stage
relayout is already queued to make sure we still go through all the
previously queued "shallow" relayouts. That shouldn't hurt performance,
too, because as soon as an actor got allocated once, it doesn't need an
allocation anymore and should bail out in clutter_actor_allocate() as
long as it's absolute position didn't change.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2538

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1173


(cherry picked from commit e74c2e42cf)
2020-04-07 16:47:32 +00:00
Jonas Ådahl
c8986d19e5 window: Check aliveness a bit less aggressively
Currently we check whether a window is alive everytime it's focused.
This means that an application that doesn't respond to the check-alive
event during startup always showing the "application froze" dialog,
without the user ever trying to interact with it.

An example where this tends to to happen is with games, and for this
particular scenario, it's purely an annoyance, as I never tried to
interact with the game window in the first place, so I don't care that
it's not responding - it's loading.

To avoid these unnecessary particular "app-is-frozen" popups, remove the
alive check from the focus function, and instead move it back to the
"meta_window_activate_full()" call. To also trigger it slightly more
often, also add it to the path that triggers the window focus when a
user actively clicks on the window.

This means that we currently check whether a window is alive on:

  * Any time the window is activated. This means e.g. alt-tab or
    selecting the window in the overview.
  * The user clicks on the window.

Note that the second only works for an already focused window on
Wayland, as on X11, we don't refocus it. This particular case isn't
changed with this commit, as we didn't call meta_window_focus() to begin
with here.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1182


(cherry picked from commit 8df3b21a51)
2020-04-07 13:23:21 +00:00
Christian Rauch
7baabc7ed0 x11: fix compilation if 'libwacom=false'
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1168


(cherry picked from commit a8f6cada88)
2020-04-06 14:57:57 +00:00
Dušan Kazik
b0709504ea Update Slovak translation 2020-04-05 20:22:08 +00:00
Jonas Ådahl
7e94311e2e window-actor: Set viewport when blitting to screencast fb
This fixes an issue where a non-maximized screen casted window would be
stretched to fill the whole screen cast stream, instead of just the crop
that corresponds to the current window size.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1174


(cherry picked from commit a6f94696e2)
2020-04-03 16:30:26 +00:00
Simon McVittie
e339a57ddf cogl: Defend against empty or unallocated framebuffers
It isn't immediately obvious that this is impossible, because there's some
"action at a distance" going on with framebuffers that have their size
set lazily, after their textures get allocated; so let's make this a
critical warning rather than crashing.

In particular, this works around a crash when gnome-shell tries to blur a
background that hasn't yet had any space allocated for it - which it seems
is really an actor layout bug, but more robustness seems good to have.

Workaround for <https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2538>.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1172

Signed-off-by: Simon McVittie <smcv@debian.org>

(cherry picked from commit c389aadff9)
2020-04-03 13:49:34 +02:00
Simon McVittie
e3b2b90c72 cogl: Don't allow creating sized textures with 0 pixels
A texture with no pixels isn't a useful thing to have, and breaks
assumptions elsewhere. For example, CoglFramebuffer assumes that after
a texture has been allocated, it will have width and height both greater
than 0.

In particular, this works around a crash when gnome-shell tries to blur a
background that hasn't yet had any space allocated for it - which it seems
is really an actor layout bug, but more robustness seems good to have.

Workaround for <https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2538>.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1172

Signed-off-by: Simon McVittie <smcv@debian.org>

(cherry picked from commit 37eda498f2)
2020-04-03 13:48:46 +02:00
Daniel van Vugt
6f094bd399 clutter/master-clock-default: Sync timelines to hardware vsync
Previously clutter timelines advanced according to `g_source_get_time`.
But that meant the spatial stepping of animations was visibly sensitive to
any irregularities in the main loop. It also represented a time older [1]
than the intended presentation time of each frame.

Now we instead use `master_clock_get_next_presentation_time`. This ensures
we get the smoothness of hardware vsync as well as being closer to the
actual presentation time.

This means, for example, backends like Xorg that move the hardware cursor
independently of repaints will have their animations more closely matching
the hardware cursor position. So the cursor appears to stick more closely
when dragging windows or on the lock screen etc.

[1] "older" = (refresh_interval - sync_delay) = ~14ms for 60Hz

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/25

https://gitlab.gnome.org/GNOME/mutter/merge_requests/724
2020-04-03 10:59:36 +00:00
Daniel van Vugt
2c805524b4 clutter/stage: Add API to get_next_presentation_time
https://gitlab.gnome.org/GNOME/mutter/merge_requests/724
2020-04-03 10:59:36 +00:00
Andre Moreira Magalhaes
95c1baf3d1 clutter/click-action: Do not process captured event if action is disabled
Disabling a click action after a button-press but before a
button-release is captured makes ClutterClickAction connect to
captured-event and never disconnect.

This change fixes it by making sure the captured-event is only
processed if the action is still enabled, otherwise releasing
the action (reset state) and propagating the event.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1170


(cherry picked from commit 5f5ce08ba4)
2020-04-02 17:09:24 +00:00
Georges Basile Stavracas Neto
6f9b5edd4d tests/actor-pick: Allocate actor before picking
Picking now only happens on allocated actors, but the
callback in the actor-pick test is not waiting for the
stage to run an allocation cycle. Ideally, we'd wait
for this cycle, but for now, forcing an allocation works
as well.

Allocate the overlay actor in the actor-pick test.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169


(cherry picked from commit 7f488e3e1d)
2020-03-31 23:13:42 +00:00
Georges Basile Stavracas Neto
31809e1214 tests/actor-pick: Remove tabs
They're evil.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169


(cherry picked from commit 059d2144b2)
2020-03-31 23:13:15 +00:00
Andre Moreira Magalhaes
82f3bdd14e clutter/actor: Fix pick when actor is not allocated
When selecting the pick regions for an actor we were not considering
whether the actor was allocated and that was causing issues where the
preferred width/height of the actor was used when deciding whether
the actor should be considered as a pick target.

Check if the actor has a valid allocation, in addition to being mapped
and being in pick mode, in clutter_actor_should_pick_paint().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1169


(cherry picked from commit 902302a174)
2020-03-31 23:12:44 +00:00
554 changed files with 38889 additions and 21957 deletions

View File

@@ -1,10 +1,9 @@
image: registry.gitlab.gnome.org/gnome/mutter/master:v4 image: registry.gitlab.gnome.org/gnome/mutter/master:v3
stages: stages:
- review - review
- build - build
- test - test
- coverage
check-commit-log: check-commit-log:
stage: review stage: review
@@ -18,7 +17,7 @@ check-commit-log:
build-mutter: build-mutter:
stage: build stage: build
script: script:
- meson . build -Dbuildtype=debugoptimized -Db_coverage=true -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr - meson . build -Dbuildtype=debugoptimized -Degl_device=true -Dwayland_eglstream=true --werror --prefix /usr
- ninja -C build - ninja -C build
- ninja -C build install - ninja -C build install
artifacts: artifacts:
@@ -36,8 +35,9 @@ build-without-opengl-and-glx:
- ninja -C build - ninja -C build
- ninja -C build install - ninja -C build install
artifacts: artifacts:
expire_in: 1 day
paths: paths:
- build/meson-logs - build
only: only:
- merge_requests - merge_requests
- /^.*$/ - /^.*$/
@@ -49,8 +49,9 @@ build-without-native-backend-and-wayland:
- ninja -C build - ninja -C build
- ninja -C build install - ninja -C build install
artifacts: artifacts:
expire_in: 1 day
paths: paths:
- build/meson-logs - build
only: only:
- merge_requests - merge_requests
- /^.*$/ - /^.*$/
@@ -65,6 +66,7 @@ test-mutter:
G_SLICE: "always-malloc" G_SLICE: "always-malloc"
MALLOC_CHECK_: "3" MALLOC_CHECK_: "3"
NO_AT_BRIDGE: "1" NO_AT_BRIDGE: "1"
MALLOC_PERTURB_: "123"
script: script:
- dconf update - dconf update
- mkdir -m 700 $XDG_RUNTIME_DIR - mkdir -m 700 $XDG_RUNTIME_DIR
@@ -72,30 +74,10 @@ test-mutter:
- > - >
dbus-run-session -- xvfb-run -s '+iglx -noreset' dbus-run-session -- xvfb-run -s '+iglx -noreset'
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv
artifacts:
expire_in: 1 day
paths:
- build
only: only:
- merge_requests - merge_requests
- /^.*$/ - /^.*$/
test-mutter-coverage:
stage: coverage
dependencies:
- test-mutter
script:
- ninja -C build coverage
- cat build/meson-logs/coverage.txt
artifacts:
paths:
- build/meson-logs
when: manual
except:
refs:
- tags
- master
can-build-gnome-shell: can-build-gnome-shell:
stage: test stage: test
dependencies: dependencies:

View File

@@ -1,27 +1,32 @@
# Rebuild and push with # Rebuild and push with
# #
# cd .gitlab-ci/ # cd .gitlab-ci/
# podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v4 . # podman build --format docker --no-cache -t registry.gitlab.gnome.org/gnome/mutter/master:v3 .
# podman push registry.gitlab.gnome.org/gnome/mutter/master:v4 # podman push registry.gitlab.gnome.org/gnome/mutter/master:v3
# #
FROM fedora:32 FROM fedora:31
RUN dnf -y update && dnf -y upgrade && \ RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(builddep)' && \ dnf install -y 'dnf-command(builddep)' && \
dnf install -y 'dnf-command(copr)' && \ dnf install -y 'dnf-command(copr)' && \
dnf copr enable -y fmuellner/gnome-shell-ci && \
dnf copr enable -y jadahl/mutter-ci && \ dnf copr enable -y jadahl/mutter-ci && \
dnf -y update && dnf -y upgrade && \
dnf builddep -y mutter --setopt=install_weak_deps=False && \ dnf builddep -y mutter && \
# Until Fedora catches up with new build-deps
dnf install -y 'pkgconfig(graphene-gobject-1.0)' 'pkgconfig(sysprof-capture-3)' && \
# For running unit tests # For running unit tests
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 \ dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 '*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center && \
'*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center gcovr \
--setopt=install_weak_deps=False && \
# GNOME Shell # GNOME Shell
dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \ dnf builddep -y gnome-shell --setopt=install_weak_deps=False && \
dnf remove -y gnome-bluetooth-libs-devel && \ dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel upower-devel python3-devel && \
dnf remove -y --noautoremove mutter mutter-devel && \ dnf remove -y --noautoremove mutter mutter-devel && \
dnf upgrade -y 'pkgconfig(libpipewire-0.3)' && \
dnf clean all dnf clean all

91
NEWS
View File

@@ -1,62 +1,45 @@
3.37.2 3.36.1
====== ======
* Fix move-to-center keybinding with multiple monitors [Sergey; #1073] * Fix hardware cursor on GPU hotplpug [Pekka; !1097]
* Fix stuck buttons when a virtual device is destroyed [Carlos; !1239] * Fix black areas around XWayland windows when resizing [Robert, Olivier; !1091]
* Use workarea when centering new windows [Akatsuki; #964] * Fix applying wrong scale to monitors on X11 [Jonas; !1118]
* Limit mipmap levels when rendering background [Daniel; !1003] * Fix moving/resizing windows via keyboard on wayland [Alynx; !997]
* Broadcast clipboard/primary offers [Carlos; !1253] * Fix locate-pointer feature interfering with keybindings [Carlos; !1014]
* Support primary-selection protocol from wayland-protocols [Carlos; !1255] * Add support for middle-click emulation [Andrew; !256]
* Fix monitor screen cast on X11 [Jonas Å.; !1251] * Fix freeze when moving cursor between scaled monitors [Robert; !1125]
* Support a "blank" cursor type [Florian; !1244] * Fix popup misplacement with focus-follows-mouse [Jonas Å.; !1122]
* Improve stage view damage tracking [Jonas Å.; !1237] * Fix misplaced cursor in preedit strings [Carlos; !1132]
* Implement touch-mode detecation for the X11 backend [Carlos; !1278] * Support mirroring with proprietary Nvidia driver [Jonas Å.; !1098]
* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277] * Support tablets with multiple mode switch buttons in a group [Carlos; !970]
* Optimize actor allocations [Jonas D.; !1247] * Ignore foreground color for color glyphs (emojis) [Carlos; !1148]
* Fixed crashes [Daniel, Carlos, Jonas Å., Jonas D.; !1256, !1258, !1217, !1280] * Allow pad mode switches while showing OSD [Carlos; !975]
* Misc. bug fixes and cleanups [Christian, Jonas D., Olivier, Ting-Wei, * Fix positioning of OSD for display-attached tablets [Carlos; !971]
Jonas Å., Marco, Corentin, Daniel, Robert, Niels, Florian, Simon; !1231, * Respect configured RANDR panning on X11 [Jonas Å.; !1085]
!1228, !1238, !1229, !1192, !1236, !1171, !1134, #1126, !1234, !1230, !1210, * Use correct texture filtering with scaled displays [Jonas; !1124]
!1242, !1243, !1252, !1113, !1232, !1259, !1245, !1265, !1180, !1261, !788, * Fix cursor hotspots in virtual machines [Jonas Å.; !1136]
!1264, !1235, !1218, !1150, !1274, !1271, !1279, !1283, !1272] * Fix build with GLES and no GL [Georges; !1151]
* Work around Firefox bug when copying images on wayland [Robert; !1141]
* Fix wrong cursor rotation on rotated displays [Hans; !1153]
* Fix glitches in window screencasts [Georges; !1129]
* Fix IM support for deleting surrounding text [Takao, Carlos; #539]
* Fix map animation of maximized windows [Robert; !1164]
* Fixed crashes [Jonas Å., Carlos, Florian, Robert; !1120, !1121,
#917, #1132, #1083, !1147, #1147]
* Misc. bug fixes and cleanups [Jonas Å., Olivier, Mart, Sebastian, Corentin,
Andre, Daniel, Robert, Carlos, Peter, Georges, Jonas D., Florian, Christian;
!1115, !1102, !1104, !1106, !1117, !1119, !1101, !1123, #1124, !1130, !1131,
!1133, #1065, !1108, !1144, !1145, !1109, !1059, !1107, !999, !1152, #1128,
!1155, !1156, !1158, !1157, #1146, !1161, !1163]
Contributors: Contributors:
Marco Trevisan (Treviño), Akatsuki, Jonas Dreßler, Olivier Fourdan, Jonas Dreßler, Olivier Fourdan, Takao Fujiwara, Carlos Garnacho, Andrew Gaul,
Carlos Garnacho, Niels De Graef, Ting-Wei Lan, Robert Mader, Simon McVittie, Hans de Goede, Peter Hutterer, Sebastian Keller, Robert Mader,
Florian Müllner, Corentin Noël, Christian Rauch, Daniel van Vugt, Andre Moreira Magalhaes, Florian Müllner, Georges Basile Stavracas Neto,
Sergey Zigachev, Jonas Ådahl Corentin Noël, Pekka Paalanen, Christian Rauch, Mart Raudsepp,
Daniel van Vugt, Alynx Zhou, Jonas Ådahl
3.37.1
======
* Fix screencasting non-maximized windows [Jonas Å.; !1174]
* Make window-aliveness checks less aggressive [Jonas Å.; !1182]
* Fix stylus coordinates when using screen rotation [Jonas T.; #1118]
* Preserve keyboard state on VT switch [Olivier; !1185]
* Remove Clutter's drag and drop actions [Jonas D.; !789]
* Cancel clicks/gestures actions on disable [Georges; !1188]
* Fix various clipboard issues [Carlos; !1186, !1198, !1203, !1204, !1206]
* Fix trackball button scrolling [Phillip; #1120]
* Fix tiled monitor support [Jonas; !1199]
* Support unredirecting fullscreen wayland surfaces [Jonas Å.; !798]
* Support area screencasts [Jonas Å.; !1207]
* Synchronize shadows to server-side decorations [Olivier; !1214]
* Allow inhibiting remote access [Jonas Å.; !1212]
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
* Fixed crashes [Jonas, D., Carlos; !1173, !1183, !1012]
* Misc. bug fixes and cleanups [Andre, Georges, Christian, Jonas Å., Andre,
Simon, Florian, Carlos, Adam, Marco, Thomas, Elias, Pekka, Jonas D.,
Laurent; !1169, !1168, !1166, !1170, !1167, !1172, !1175, !1176, !1184,
!1126, !1187, !1191, !1195, !1179, !1200, !1193, !1209, !1213, !1208,
#1074, !1223]
Contributors:
Marco Trevisan (Treviño), Elias Aebi, Thomas Hindoe Paaboel Andersen,
Laurent Bigonville, Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Adam Jackson, Andre Moreira Magalhaes, Simon McVittie, Florian Müllner,
Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger,
Phillip Wood, Jonas Ådahl
Translators: Translators:
Dušan Kazik [sk], Christian Kirbach [de] Марко Костић [sr], Daniel Șerbănescu [ro]
3.36.0 3.36.0
====== ======

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

@@ -63,7 +63,7 @@ struct _CallyStagePrivate
G_DEFINE_TYPE_WITH_CODE (CallyStage, G_DEFINE_TYPE_WITH_CODE (CallyStage,
cally_stage, cally_stage,
CALLY_TYPE_ACTOR, CALLY_TYPE_GROUP,
G_ADD_PRIVATE (CallyStage) G_ADD_PRIVATE (CallyStage)
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW, G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
cally_stage_window_interface_init)); cally_stage_window_interface_init));

View File

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

View File

@@ -36,8 +36,10 @@
#include "cally.h" #include "cally.h"
#include "cally-actor.h" #include "cally-actor.h"
#include "cally-group.h"
#include "cally-stage.h" #include "cally-stage.h"
#include "cally-text.h" #include "cally-text.h"
#include "cally-rectangle.h"
#include "cally-clone.h" #include "cally-clone.h"
#include "cally-factory.h" #include "cally-factory.h"
@@ -50,8 +52,10 @@
/* factories initialization*/ /* factories initialization*/
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new) 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_STAGE, cally_stage, cally_stage_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new) CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle_new)
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new) CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
/** /**
@@ -69,8 +73,10 @@ cally_accessibility_init (void)
{ {
/* setting the factories */ /* setting the factories */
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor); 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_STAGE, cally_stage);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text); CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_RECTANGLE, cally_rectangle);
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone); CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone);
/* Initialize the CallyUtility class */ /* Initialize the CallyUtility class */

View File

@@ -26,7 +26,9 @@
#include "cally-actor.h" #include "cally-actor.h"
#include "cally-clone.h" #include "cally-clone.h"
#include "cally-factory.h" #include "cally-factory.h"
#include "cally-group.h"
#include "cally-main.h" #include "cally-main.h"
#include "cally-rectangle.h"
#include "cally-root.h" #include "cally-root.h"
#include "cally-stage.h" #include "cally-stage.h"
#include "cally-text.h" #include "cally-text.h"

View File

@@ -33,11 +33,28 @@
G_BEGIN_DECLS 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 typedef struct _ClutterActionClass ClutterActionClass;
G_DECLARE_DERIVABLE_TYPE (ClutterAction, clutter_action,
CLUTTER, ACTION, ClutterActorMeta); /**
* 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: * ClutterActionClass:
@@ -61,6 +78,9 @@ struct _ClutterActionClass
void (* _clutter_action8) (void); void (* _clutter_action8) (void);
}; };
CLUTTER_EXPORT
GType clutter_action_get_type (void) G_GNUC_CONST;
/* ClutterActor API */ /* ClutterActor API */
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_add_action (ClutterActor *self, void clutter_actor_add_action (ClutterActor *self,

View File

@@ -615,32 +615,6 @@ clutter_actor_box_scale (ClutterActorBox *box,
box->y2 *= 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, G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
clutter_actor_box_copy, clutter_actor_box_copy,
clutter_actor_box_free, clutter_actor_box_free,

View File

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

View File

@@ -33,13 +33,31 @@
G_BEGIN_DECLS 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 typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate;
G_DECLARE_DERIVABLE_TYPE (ClutterActorMeta, clutter_actor_meta, typedef struct _ClutterActorMetaClass ClutterActorMetaClass;
CLUTTER, ACTOR_META, GInitiallyUnowned);
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: * ClutterActorMetaClass:
@@ -69,9 +87,6 @@ struct _ClutterActorMetaClass
void (* set_actor) (ClutterActorMeta *meta, void (* set_actor) (ClutterActorMeta *meta,
ClutterActor *actor); ClutterActor *actor);
void (* set_enabled) (ClutterActorMeta *meta,
gboolean is_enabled);
/*< private >*/ /*< private >*/
void (* _clutter_meta1) (void); void (* _clutter_meta1) (void);
void (* _clutter_meta2) (void); void (* _clutter_meta2) (void);
@@ -79,8 +94,12 @@ struct _ClutterActorMetaClass
void (* _clutter_meta4) (void); void (* _clutter_meta4) (void);
void (* _clutter_meta5) (void); void (* _clutter_meta5) (void);
void (* _clutter_meta6) (void); void (* _clutter_meta6) (void);
void (* _clutter_meta7) (void);
}; };
CLUTTER_EXPORT
GType clutter_actor_meta_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_meta_set_name (ClutterActorMeta *meta, void clutter_actor_meta_set_name (ClutterActorMeta *meta,
const gchar *name); const gchar *name);

View File

@@ -110,12 +110,35 @@ typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor
typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor, typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor,
gpointer user_data); gpointer user_data);
typedef struct _AnchorCoord AnchorCoord;
typedef struct _SizeRequest SizeRequest; typedef struct _SizeRequest SizeRequest;
typedef struct _ClutterLayoutInfo ClutterLayoutInfo; typedef struct _ClutterLayoutInfo ClutterLayoutInfo;
typedef struct _ClutterTransformInfo ClutterTransformInfo; typedef struct _ClutterTransformInfo ClutterTransformInfo;
typedef struct _ClutterAnimationInfo ClutterAnimationInfo; 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 */
graphene_point3d_t units;
} v;
};
struct _SizeRequest struct _SizeRequest
{ {
guint age; guint age;
@@ -160,15 +183,24 @@ ClutterLayoutInfo * _clutter_actor_peek_layout_info
struct _ClutterTransformInfo struct _ClutterTransformInfo
{ {
/* rotation */ /* rotation (angle and center) */
gdouble rx_angle; gdouble rx_angle;
AnchorCoord rx_center;
gdouble ry_angle; gdouble ry_angle;
AnchorCoord ry_center;
gdouble rz_angle; gdouble rz_angle;
AnchorCoord rz_center;
/* scaling */ /* scaling */
gdouble scale_x; gdouble scale_x;
gdouble scale_y; gdouble scale_y;
gdouble scale_z; gdouble scale_z;
AnchorCoord scale_center;
/* anchor point */
AnchorCoord anchor;
/* translation */ /* translation */
graphene_point3d_t translation; graphene_point3d_t translation;
@@ -281,18 +313,14 @@ void _clutter_actor_detach_clone
void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor); void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor); void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
void _clutter_actor_queue_only_relayout (ClutterActor *actor); void _clutter_actor_queue_only_relayout (ClutterActor *actor);
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor); void _clutter_actor_queue_update_resource_scale_recursive (ClutterActor *actor);
float clutter_actor_get_real_resource_scale (ClutterActor *actor); gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
float *resource_scale);
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self, ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
CoglTexture *texture); CoglTexture *texture);
void clutter_actor_update_stage_views (ClutterActor *self,
int phase);
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_ACTOR_PRIVATE_H__ */ #endif /* __CLUTTER_ACTOR_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -142,6 +142,11 @@ struct _ClutterActor
* ClutterActorClass: * ClutterActorClass:
* @show: signal class handler for #ClutterActor::show; it must chain * @show: signal class handler for #ClutterActor::show; it must chain
* up to the parent's implementation * 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 * @hide: signal class handler for #ClutterActor::hide; it must chain
* up to the parent's implementation * up to the parent's implementation
* @hide_all: virtual function for containers and composite actors, to * @hide_all: virtual function for containers and composite actors, to
@@ -170,18 +175,12 @@ struct _ClutterActor
* @get_preferred_height: virtual function, used when querying the minimum * @get_preferred_height: virtual function, used when querying the minimum
* and natural heights of an actor for a given width; it is used by * and natural heights of an actor for a given width; it is used by
* clutter_actor_get_preferred_height() * clutter_actor_get_preferred_height()
* @allocate: virtual function, used when setting the coordinates of an * @allocate: virtual function, used when settings the coordinates of an
* actor; it is used by clutter_actor_allocate(); when overriding this * actor; it is used by clutter_actor_allocate(); it must chain up to
* function without chaining up, clutter_actor_set_allocation() must be * the parent's implementation, or call clutter_actor_set_allocation()
* called and children must be allocated by the implementation, when
* chaining up though, those things will be done by the parent's
* implementation.
* @apply_transform: virtual function, used when applying the transformations * @apply_transform: virtual function, used when applying the transformations
* to an actor before painting it or when transforming coordinates or * to an actor before painting it or when transforming coordinates or
* the allocation; if the transformation calculated by this function may * the allocation; it must chain up to the parent's implementation
* have changed, the cached transformation must be invalidated by calling
* clutter_actor_invalidate_transform(); it must chain up to the parent's
* implementation
* @parent_set: signal class handler for the #ClutterActor::parent-set * @parent_set: signal class handler for the #ClutterActor::parent-set
* @destroy: signal class handler for #ClutterActor::destroy. It must * @destroy: signal class handler for #ClutterActor::destroy. It must
* chain up to the parent's implementation * chain up to the parent's implementation
@@ -224,6 +223,7 @@ struct _ClutterActorClass
/*< public >*/ /*< public >*/
void (* show) (ClutterActor *self); void (* show) (ClutterActor *self);
void (* show_all) (ClutterActor *self);
void (* hide) (ClutterActor *self); void (* hide) (ClutterActor *self);
void (* hide_all) (ClutterActor *self); void (* hide_all) (ClutterActor *self);
void (* realize) (ClutterActor *self); void (* realize) (ClutterActor *self);
@@ -253,7 +253,8 @@ struct _ClutterActorClass
gfloat *min_height_p, gfloat *min_height_p,
gfloat *natural_height_p); gfloat *natural_height_p);
void (* allocate) (ClutterActor *self, void (* allocate) (ClutterActor *self,
const ClutterActorBox *box); const ClutterActorBox *box,
ClutterAllocationFlags flags);
/* transformations */ /* transformations */
void (* apply_transform) (ClutterActor *actor, void (* apply_transform) (ClutterActor *actor,
@@ -299,9 +300,6 @@ struct _ClutterActorClass
gboolean (* touch_event) (ClutterActor *self, gboolean (* touch_event) (ClutterActor *self,
ClutterTouchEvent *event); ClutterTouchEvent *event);
gboolean (* has_accessible) (ClutterActor *self); gboolean (* has_accessible) (ClutterActor *self);
void (* resource_scale_changed) (ClutterActor *self);
float (* calculate_resource_scale) (ClutterActor *self,
int phase);
/*< private >*/ /*< private >*/
/* padding for future expansion */ /* padding for future expansion */
@@ -417,29 +415,38 @@ void clutter_actor_get_preferred_size
gfloat *natural_height_p); gfloat *natural_height_p);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_allocate (ClutterActor *self, void clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box); const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_allocate_preferred_size (ClutterActor *self); void clutter_actor_allocate_preferred_size (ClutterActor *self,
ClutterAllocationFlags flags);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_allocate_available_size (ClutterActor *self, void clutter_actor_allocate_available_size (ClutterActor *self,
gfloat x, gfloat x,
gfloat y, gfloat y,
gfloat available_width, gfloat available_width,
gfloat available_height); gfloat available_height,
ClutterAllocationFlags flags);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_allocate_align_fill (ClutterActor *self, void clutter_actor_allocate_align_fill (ClutterActor *self,
const ClutterActorBox *box, const ClutterActorBox *box,
gdouble x_align, gdouble x_align,
gdouble y_align, gdouble y_align,
gboolean x_fill, gboolean x_fill,
gboolean y_fill); gboolean y_fill,
ClutterAllocationFlags flags);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_set_allocation (ClutterActor *self, void clutter_actor_set_allocation (ClutterActor *self,
const ClutterActorBox *box); const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_get_allocation_box (ClutterActor *self, void clutter_actor_get_allocation_box (ClutterActor *self,
ClutterActorBox *box); ClutterActorBox *box);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
graphene_point3d_t *verts);
CLUTTER_EXPORT
gboolean clutter_actor_has_allocation (ClutterActor *self); gboolean clutter_actor_has_allocation (ClutterActor *self);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_actor_set_size (ClutterActor *self, void clutter_actor_set_size (ClutterActor *self,
@@ -593,7 +600,8 @@ gboolean clutter_actor_get_paint_box
ClutterActorBox *box); ClutterActorBox *box);
CLUTTER_EXPORT CLUTTER_EXPORT
float clutter_actor_get_resource_scale (ClutterActor *self); gboolean clutter_actor_get_resource_scale (ClutterActor *self,
gfloat *resource_scale);
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_actor_has_overlaps (ClutterActor *self); gboolean clutter_actor_has_overlaps (ClutterActor *self);
@@ -918,15 +926,6 @@ void clutter_actor_pick_box (ClutterActor *self,
ClutterPickContext *pick_context, ClutterPickContext *pick_context,
const ClutterActorBox *box); const ClutterActorBox *box);
CLUTTER_EXPORT
GList * clutter_actor_peek_stage_views (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_invalidate_transform (ClutterActor *self);
CLUTTER_EXPORT
ClutterFrameClock * clutter_actor_pick_frame_clock (ClutterActor *self);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_ACTOR_H__ */ #endif /* __CLUTTER_ACTOR_H__ */

View File

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

View File

@@ -67,12 +67,6 @@ void clutter_align_constraint_set_align_axis (ClutterAlignConstrai
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align); ClutterAlignAxis clutter_align_constraint_get_align_axis (ClutterAlignConstraint *align);
CLUTTER_EXPORT 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, void clutter_align_constraint_set_factor (ClutterAlignConstraint *align,
gfloat factor); gfloat factor);
CLUTTER_EXPORT CLUTTER_EXPORT

View File

@@ -27,23 +27,35 @@
* @short_description: Interface for animatable classes * @short_description: Interface for animatable classes
* *
* #ClutterAnimatable is an interface that allows a #GObject class * #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 * Each #ClutterAnimatable should implement the
* #ClutterAnimatableInterface.interpolate_property() virtual function of the * #ClutterAnimatableInterface.interpolate_property() virtual function of the
* interface to compute the animation state between two values of an interval * interface to compute the animation state between two values of an interval
* depending on a progress factor, expressed as a floating point value. * 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 * #ClutterAnimatable is available since Clutter 1.0
*/ */
#include "clutter-build-config.h" #include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-animatable.h" #include "clutter-animatable.h"
#include "clutter-interval.h" #include "clutter-interval.h"
#include "clutter-debug.h" #include "clutter-debug.h"
#include "clutter-private.h" #include "clutter-private.h"
#include "deprecated/clutter-animation.h"
G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT); G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
static void static void
@@ -194,25 +206,3 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
else else
return clutter_interval_compute_value (interval, progress, value); 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

@@ -42,6 +42,8 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
/** /**
* ClutterAnimatableInterface: * ClutterAnimatableInterface:
* @animate_property: virtual function for custom interpolation of a
* property. This virtual function is deprecated
* @find_property: virtual function for retrieving the #GParamSpec of * @find_property: virtual function for retrieving the #GParamSpec of
* an animatable property * an animatable property
* @get_initial_state: virtual function for retrieving the initial * @get_initial_state: virtual function for retrieving the initial
@@ -50,7 +52,9 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
* animatable property * animatable property
* @interpolate_value: virtual function for interpolating the progress * @interpolate_value: virtual function for interpolating the progress
* of a property * 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 * Since: 1.0
*/ */
@@ -60,6 +64,13 @@ struct _ClutterAnimatableInterface
GTypeInterface parent_iface; GTypeInterface parent_iface;
/*< public >*/ /*< 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, GParamSpec *(* find_property) (ClutterAnimatable *animatable,
const gchar *property_name); const gchar *property_name);
void (* get_initial_state) (ClutterAnimatable *animatable, void (* get_initial_state) (ClutterAnimatable *animatable,
@@ -73,7 +84,6 @@ struct _ClutterAnimatableInterface
ClutterInterval *interval, ClutterInterval *interval,
gdouble progress, gdouble progress,
GValue *value); GValue *value);
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
}; };
CLUTTER_EXPORT CLUTTER_EXPORT
@@ -94,9 +104,6 @@ gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
gdouble progress, gdouble progress,
GValue *value); GValue *value);
CLUTTER_EXPORT
ClutterActor * clutter_animatable_get_actor (ClutterAnimatable *animatable);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_ANIMATABLE_H__ */ #endif /* __CLUTTER_ANIMATABLE_H__ */

View File

@@ -30,7 +30,9 @@
#ifndef __GI_SCANNER__ #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 (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 (ClutterAlignConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, 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 (ClutterBindConstraint, g_object_unref)
@@ -41,15 +43,19 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBoxLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBrightnessContrastEffect, 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 (ClutterCanvas, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterChildMeta, 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 (ClutterClone, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColorizeEffect, 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 (ClutterConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeformEffect, 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 (ClutterDesaturateEffect, 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 (ClutterEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFixedLayout, 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 (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 (ClutterGridLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterImage, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterImage, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInputDevice, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInputDevice, g_object_unref)

View File

@@ -53,8 +53,6 @@ struct _ClutterBackend
gfloat units_per_em; gfloat units_per_em;
gint32 units_serial; gint32 units_serial;
float fallback_resource_scale;
ClutterStageWindow *stage_window; ClutterStageWindow *stage_window;
ClutterInputMethod *input_method; ClutterInputMethod *input_method;
@@ -136,12 +134,6 @@ void clutter_set_allowed_drivers (const c
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterStageWindow * clutter_backend_get_stage_window (ClutterBackend *backend); 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);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */ #endif /* __CLUTTER_BACKEND_PRIVATE_H__ */

View File

@@ -601,8 +601,6 @@ clutter_backend_init (ClutterBackend *self)
self->units_serial = 1; self->units_serial = 1;
self->dummy_onscreen = NULL; self->dummy_onscreen = NULL;
self->fallback_resource_scale = 1.f;
} }
void void
@@ -1033,16 +1031,3 @@ clutter_backend_get_default_seat (ClutterBackend *backend)
return CLUTTER_BACKEND_GET_CLASS (backend)->get_default_seat (backend); 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;
}

View File

@@ -406,7 +406,8 @@ get_actor_align_factor (ClutterActorAlign alignment)
static void static void
clutter_bin_layout_allocate (ClutterLayoutManager *manager, clutter_bin_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation) const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{ {
gfloat allocation_x, allocation_y; gfloat allocation_x, allocation_y;
gfloat available_w, available_h; gfloat available_w, available_h;
@@ -514,7 +515,8 @@ clutter_bin_layout_allocate (ClutterLayoutManager *manager,
clutter_actor_allocate_align_fill (child, &child_alloc, clutter_actor_allocate_align_fill (child, &child_alloc,
x_align, y_align, x_align, y_align,
x_fill, y_fill); x_fill, y_fill,
flags);
} }
} }

View File

@@ -38,14 +38,12 @@
* *
* |[<!-- language="C" --> * |[<!-- language="C" -->
* // source * // source
* rect[0] = clutter_actor_new (); * rect[0] = clutter_rectangle_new_with_color (&red_color);
* clutter_actor_set_background_color (rect[0], &red_color);
* clutter_actor_set_position (rect[0], x_pos, y_pos); * clutter_actor_set_position (rect[0], x_pos, y_pos);
* clutter_actor_set_size (rect[0], 100, 100); * clutter_actor_set_size (rect[0], 100, 100);
* *
* // second rectangle * // second rectangle
* rect[1] = clutter_actor_new (); * rect[1] = clutter_rectangle_new_with_color (&green_color);
* clutter_actor_set_background_color (rect[1], &green_color);
* clutter_actor_set_size (rect[1], 100, 100); * clutter_actor_set_size (rect[1], 100, 100);
* clutter_actor_set_opacity (rect[1], 0); * clutter_actor_set_opacity (rect[1], 0);
* *
@@ -55,8 +53,7 @@
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint); * clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
* *
* // third rectangle * // third rectangle
* rect[2] = clutter_actor_new (); * rect[2] = clutter_rectangle_new_with_color (&blue_color);
* clutter_actor_set_background_color (rect[2], &blue_color);
* clutter_actor_set_size (rect[2], 100, 100); * clutter_actor_set_size (rect[2], 100, 100);
* clutter_actor_set_opacity (rect[2], 0); * clutter_actor_set_opacity (rect[2], 0);
* *
@@ -168,9 +165,6 @@ clutter_bind_constraint_update_preferred_size (ClutterConstraint *constraint,
bind->coordinate == CLUTTER_BIND_ALL)) bind->coordinate == CLUTTER_BIND_ALL))
return; return;
if (clutter_actor_contains (bind->source, actor))
return;
switch (direction) switch (direction)
{ {
case CLUTTER_ORIENTATION_HORIZONTAL: case CLUTTER_ORIENTATION_HORIZONTAL:

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 CLUTTER_EXPORT
gboolean clutter_box_layout_get_pack_start (ClutterBoxLayout *layout); 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 G_END_DECLS
#endif /* __CLUTTER_BOX_LAYOUT_H__ */ #endif /* __CLUTTER_BOX_LAYOUT_H__ */

View File

@@ -159,8 +159,7 @@ static inline void
click_action_set_pressed (ClutterClickAction *action, click_action_set_pressed (ClutterClickAction *action,
gboolean is_pressed) gboolean is_pressed)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
is_pressed = !!is_pressed; is_pressed = !!is_pressed;
@@ -175,8 +174,7 @@ static inline void
click_action_set_held (ClutterClickAction *action, click_action_set_held (ClutterClickAction *action,
gboolean is_held) gboolean is_held)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
is_held = !!is_held; is_held = !!is_held;
@@ -191,8 +189,7 @@ static gboolean
click_action_emit_long_press (gpointer data) click_action_emit_long_press (gpointer data)
{ {
ClutterClickAction *action = data; ClutterClickAction *action = data;
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
ClutterActor *actor; ClutterActor *actor;
gboolean result; gboolean result;
@@ -216,8 +213,7 @@ click_action_emit_long_press (gpointer data)
static inline void static inline void
click_action_query_long_press (ClutterClickAction *action) click_action_query_long_press (ClutterClickAction *action)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
ClutterActor *actor; ClutterActor *actor;
gboolean result = FALSE; gboolean result = FALSE;
gint timeout; gint timeout;
@@ -242,7 +238,6 @@ click_action_query_long_press (ClutterClickAction *action)
if (result) if (result)
{ {
g_clear_handle_id (&priv->long_press_id, g_source_remove);
priv->long_press_id = priv->long_press_id =
clutter_threads_add_timeout (timeout, clutter_threads_add_timeout (timeout,
click_action_emit_long_press, click_action_emit_long_press,
@@ -253,8 +248,7 @@ click_action_query_long_press (ClutterClickAction *action)
static inline void static inline void
click_action_cancel_long_press (ClutterClickAction *action) click_action_cancel_long_press (ClutterClickAction *action)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
if (priv->long_press_id != 0) if (priv->long_press_id != 0)
{ {
@@ -277,8 +271,7 @@ on_event (ClutterActor *actor,
ClutterEvent *event, ClutterEvent *event,
ClutterClickAction *action) ClutterClickAction *action)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
gboolean has_button = TRUE; gboolean has_button = TRUE;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
@@ -348,12 +341,17 @@ on_captured_event (ClutterActor *stage,
ClutterEvent *event, ClutterEvent *event,
ClutterClickAction *action) ClutterClickAction *action)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
ClutterActor *actor; ClutterActor *actor;
ClutterModifierType modifier_state; ClutterModifierType modifier_state;
gboolean has_button = TRUE; gboolean has_button = TRUE;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
{
clutter_click_action_release (action);
return CLUTTER_EVENT_PROPAGATE;
}
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
switch (clutter_event_type (event)) switch (clutter_event_type (event))
@@ -441,8 +439,7 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor) ClutterActor *actor)
{ {
ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta); ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta);
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = action->priv;
clutter_click_action_get_instance_private (action);
if (priv->event_id != 0) if (priv->event_id != 0)
{ {
@@ -476,28 +473,13 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
CLUTTER_ACTOR_META_CLASS (clutter_click_action_parent_class)->set_actor (meta, actor); 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 static void
clutter_click_action_set_property (GObject *gobject, clutter_click_action_set_property (GObject *gobject,
guint prop_id, guint prop_id,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
switch (prop_id) switch (prop_id)
{ {
@@ -521,8 +503,7 @@ clutter_click_action_get_property (GObject *gobject,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
switch (prop_id) switch (prop_id)
{ {
@@ -551,8 +532,7 @@ clutter_click_action_get_property (GObject *gobject,
static void static void
clutter_click_action_dispose (GObject *gobject) clutter_click_action_dispose (GObject *gobject)
{ {
ClutterClickActionPrivate *priv = ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
g_clear_signal_handler (&priv->event_id, g_clear_signal_handler (&priv->event_id,
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject))); clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)));
@@ -572,7 +552,6 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
meta_class->set_actor = clutter_click_action_set_actor; 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->dispose = clutter_click_action_dispose;
gobject_class->set_property = clutter_click_action_set_property; gobject_class->set_property = clutter_click_action_set_property;
@@ -710,11 +689,9 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
static void static void
clutter_click_action_init (ClutterClickAction *self) clutter_click_action_init (ClutterClickAction *self)
{ {
ClutterClickActionPrivate *priv = self->priv = clutter_click_action_get_instance_private (self);
clutter_click_action_get_instance_private (self); self->priv->long_press_threshold = -1;
self->priv->long_press_duration = -1;
priv->long_press_threshold = -1;
priv->long_press_duration = -1;
} }
/** /**
@@ -754,7 +731,7 @@ clutter_click_action_release (ClutterClickAction *action)
g_return_if_fail (CLUTTER_IS_CLICK_ACTION (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) if (!priv->is_held)
return; return;
@@ -780,13 +757,9 @@ clutter_click_action_release (ClutterClickAction *action)
guint guint
clutter_click_action_get_button (ClutterClickAction *action) clutter_click_action_get_button (ClutterClickAction *action)
{ {
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0); g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action); return action->priv->press_button;
return priv->press_button;
} }
/** /**
@@ -802,13 +775,9 @@ clutter_click_action_get_button (ClutterClickAction *action)
ClutterModifierType ClutterModifierType
clutter_click_action_get_state (ClutterClickAction *action) clutter_click_action_get_state (ClutterClickAction *action)
{ {
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0); g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action); return action->priv->modifier_state;
return priv->modifier_state;
} }
/** /**
@@ -826,15 +795,11 @@ clutter_click_action_get_coords (ClutterClickAction *action,
gfloat *press_x, gfloat *press_x,
gfloat *press_y) gfloat *press_y)
{ {
ClutterClickActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTION (action)); g_return_if_fail (CLUTTER_IS_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
if (press_x != NULL) if (press_x != NULL)
*press_x = priv->press_x; *press_x = action->priv->press_x;
if (press_y != NULL) if (press_y != NULL)
*press_y = priv->press_y; *press_y = action->priv->press_y;
} }

View File

@@ -37,13 +37,32 @@
G_BEGIN_DECLS 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 typedef struct _ClutterClickAction ClutterClickAction;
G_DECLARE_DERIVABLE_TYPE (ClutterClickAction, clutter_click_action, typedef struct _ClutterClickActionPrivate ClutterClickActionPrivate;
CLUTTER, CLICK_ACTION, ClutterAction); 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: * ClutterClickActionClass:
@@ -78,6 +97,9 @@ struct _ClutterClickActionClass
void (* _clutter_click_action7) (void); void (* _clutter_click_action7) (void);
}; };
CLUTTER_EXPORT
GType clutter_click_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterAction * clutter_click_action_new (void); ClutterAction * clutter_click_action_new (void);

View File

@@ -52,8 +52,6 @@
struct _ClutterClonePrivate struct _ClutterClonePrivate
{ {
ClutterActor *clone_source; ClutterActor *clone_source;
float x_scale, y_scale;
gulong source_destroy_id; gulong source_destroy_id;
}; };
@@ -124,6 +122,8 @@ static void
clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix) clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
{ {
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorBox box, source_box;
gfloat x_scale, y_scale;
/* First chain up and apply all the standard ClutterActor /* First chain up and apply all the standard ClutterActor
* transformations... */ * transformations... */
@@ -134,7 +134,21 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
if (priv->clone_source == NULL) if (priv->clone_source == NULL)
return; return;
cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f); /* 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 static void
@@ -226,16 +240,15 @@ clutter_clone_has_overlaps (ClutterActor *actor)
static void static void
clutter_clone_allocate (ClutterActor *self, clutter_clone_allocate (ClutterActor *self,
const ClutterActorBox *box) const ClutterActorBox *box,
ClutterAllocationFlags flags)
{ {
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorClass *parent_class; ClutterActorClass *parent_class;
ClutterActorBox source_box;
float x_scale, y_scale;
/* chain up */ /* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class); 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) if (priv->clone_source == NULL)
return; return;
@@ -245,25 +258,7 @@ clutter_clone_allocate (ClutterActor *self,
*/ */
if (clutter_actor_get_parent (priv->clone_source) != NULL && if (clutter_actor_get_parent (priv->clone_source) != NULL &&
!clutter_actor_has_allocation (priv->clone_source)) !clutter_actor_has_allocation (priv->clone_source))
clutter_actor_allocate_preferred_size (priv->clone_source); clutter_actor_allocate_preferred_size (priv->clone_source, flags);
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 #if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented /* XXX - this is wrong: ClutterClone cannot clone unparented
@@ -278,7 +273,7 @@ clutter_clone_allocate (ClutterActor *self,
* paint cycle, we can safely give it as much size as it requires * paint cycle, we can safely give it as much size as it requires
*/ */
if (clutter_actor_get_parent (priv->clone_source) == NULL) 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 #endif
} }
@@ -370,9 +365,6 @@ static void
clutter_clone_init (ClutterClone *self) clutter_clone_init (ClutterClone *self)
{ {
self->priv = clutter_clone_get_instance_private (self); self->priv = clutter_clone_get_instance_private (self);
self->priv->x_scale = 1.f;
self->priv->y_scale = 1.f;
} }
/** /**

View File

@@ -9,13 +9,7 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#mesondefine CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT @CLUTTER_CONFIG_DEFINES@
#mesondefine CLUTTER_WINDOWING_X11
#mesondefine CLUTTER_INPUT_X11
#mesondefine CLUTTER_WINDOWING_GLX
#mesondefine CLUTTER_WINDOWING_EGL
#mesondefine CLUTTER_INPUT_EVDEV
#mesondefine CLUTTER_INPUT_NULL
G_END_DECLS G_END_DECLS

View File

@@ -160,26 +160,28 @@ constraint_update_preferred_size (ClutterConstraint *constraint,
} }
static void static void
clutter_constraint_set_enabled (ClutterActorMeta *meta, clutter_constraint_notify (GObject *gobject,
gboolean is_enabled) GParamSpec *pspec)
{ {
ClutterActorMetaClass *parent_class = if (strcmp (pspec->name, "enabled") == 0)
CLUTTER_ACTOR_META_CLASS (clutter_constraint_parent_class); {
ClutterActor *actor; ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
ClutterActor *actor = clutter_actor_meta_get_actor (meta);
actor = clutter_actor_meta_get_actor (meta); if (actor != NULL)
if (actor) clutter_actor_queue_relayout (actor);
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 static void
clutter_constraint_class_init (ClutterConstraintClass *klass) 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_allocation = constraint_update_allocation;
klass->update_preferred_size = constraint_update_preferred_size; klass->update_preferred_size = constraint_update_preferred_size;

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,42 +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>
typedef struct _ClutterDamageHistory ClutterDamageHistory;
ClutterDamageHistory * clutter_damage_history_new (void);
void clutter_damage_history_free (ClutterDamageHistory *history);
gboolean clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
int age);
void clutter_damage_history_record (ClutterDamageHistory *history,
const cairo_region_t *damage);
void clutter_damage_history_step (ClutterDamageHistory *history);
const cairo_region_t * clutter_damage_history_lookup (ClutterDamageHistory *history,
int age);
#endif /* CLUTTER_DAMAGE_HISTORY_H */

View File

@@ -128,9 +128,10 @@ clutter_deform_effect_deform_vertex (ClutterDeformEffect *effect,
} }
static void static void
vbo_invalidate (ClutterActor *actor, vbo_invalidate (ClutterActor *actor,
GParamSpec *pspec, const ClutterActorBox *allocation,
ClutterDeformEffect *effect) ClutterAllocationFlags flags,
ClutterDeformEffect *effect)
{ {
effect->priv->is_dirty = TRUE; effect->priv->is_dirty = TRUE;
} }
@@ -155,7 +156,7 @@ clutter_deform_effect_set_actor (ClutterActorMeta *meta,
* changes * changes
*/ */
if (actor != NULL) 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), G_CALLBACK (vbo_invalidate),
meta); meta);

View File

@@ -3,7 +3,16 @@
#define __CLUTTER_DEPRECATED_H_INSIDE__ #define __CLUTTER_DEPRECATED_H_INSIDE__
#include "deprecated/clutter-actor.h"
#include "deprecated/clutter-alpha.h"
#include "deprecated/clutter-animation.h"
#include "deprecated/clutter-box.h"
#include "deprecated/clutter-container.h" #include "deprecated/clutter-container.h"
#include "deprecated/clutter-group.h"
#include "deprecated/clutter-rectangle.h"
#include "deprecated/clutter-stage.h"
#include "deprecated/clutter-state.h"
#include "deprecated/clutter-timeline.h"
#undef __CLUTTER_DEPRECATED_H_INSIDE__ #undef __CLUTTER_DEPRECATED_H_INSIDE__

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,
graphene_rect_t *drag_area);
CLUTTER_EXPORT
void clutter_drag_action_set_drag_area (ClutterDragAction *action,
const graphene_rect_t *drag_area);
G_END_DECLS
#endif /* __CLUTTER_DRAG_ACTION_H__ */

View File

@@ -0,0 +1,527 @@
/*
* 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_clear_signal_handler (&data->capture_id, data->stage);
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));
g_clear_signal_handler (&priv->mapped_id, priv->actor);
priv->stage = NULL;
priv->actor = NULL;
}
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, NULL,
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, NULL,
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__ */

View File

@@ -230,26 +230,28 @@ clutter_effect_real_pick (ClutterEffect *effect,
} }
static void static void
clutter_effect_set_enabled (ClutterActorMeta *meta, clutter_effect_notify (GObject *gobject,
gboolean is_enabled) GParamSpec *pspec)
{ {
ClutterActorMetaClass *parent_class = if (strcmp (pspec->name, "enabled") == 0)
CLUTTER_ACTOR_META_CLASS (clutter_effect_parent_class); {
ClutterActor *actor; ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
ClutterActor *actor = clutter_actor_meta_get_actor (meta);
actor = clutter_actor_meta_get_actor (meta); if (actor != NULL)
if (actor) clutter_actor_queue_redraw (actor);
clutter_actor_queue_redraw (actor); }
parent_class->set_enabled (meta, is_enabled); if (G_OBJECT_CLASS (clutter_effect_parent_class)->notify != NULL)
G_OBJECT_CLASS (clutter_effect_parent_class)->notify (gobject, pspec);
} }
static void static void
clutter_effect_class_init (ClutterEffectClass *klass) clutter_effect_class_init (ClutterEffectClass *klass)
{ {
ClutterActorMetaClass *actor_meta_class = CLUTTER_ACTOR_META_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
actor_meta_class->set_enabled = clutter_effect_set_enabled; gobject_class->notify = clutter_effect_notify;
klass->pre_paint = clutter_effect_real_pre_paint; klass->pre_paint = clutter_effect_real_pre_paint;
klass->post_paint = clutter_effect_real_post_paint; klass->post_paint = clutter_effect_real_post_paint;

View File

@@ -190,7 +190,7 @@ typedef enum /*< prefix=CLUTTER_REQUEST >*/
* @CLUTTER_ANIMATION_LAST: last animation mode, used as a guard for * @CLUTTER_ANIMATION_LAST: last animation mode, used as a guard for
* registered global alpha functions * registered global alpha functions
* *
* The animation modes used by #ClutterAnimatable. This * The animation modes used by #ClutterAlpha and #ClutterAnimation. This
* enumeration can be expanded in later versions of Clutter. * enumeration can be expanded in later versions of Clutter.
* *
* <figure id="easing-modes"> * <figure id="easing-modes">
@@ -554,6 +554,32 @@ typedef enum /*< prefix=CLUTTER_OFFSCREEN_REDIRECT >*/
CLUTTER_OFFSCREEN_REDIRECT_ON_IDLE = 1 << 2 CLUTTER_OFFSCREEN_REDIRECT_ON_IDLE = 1 << 2
} ClutterOffscreenRedirect; } ClutterOffscreenRedirect;
/**
* ClutterAllocationFlags:
* @CLUTTER_ALLOCATION_NONE: No flag set
* @CLUTTER_ABSOLUTE_ORIGIN_CHANGED: Whether the absolute origin of the
* actor has changed; this implies that any ancestor of the actor has
* been moved.
* @CLUTTER_DELEGATE_LAYOUT: Whether the allocation should be delegated
* to the #ClutterLayoutManager instance stored inside the
* #ClutterActor:layout-manager property of #ClutterActor. This flag
* should only be used if you are subclassing #ClutterActor and
* overriding the #ClutterActorClass.allocate() virtual function, but
* you wish to use the default implementation of the virtual function
* inside #ClutterActor. Added in Clutter 1.10.
*
* Flags passed to the #ClutterActorClass.allocate() virtual function
* and to the clutter_actor_allocate() function.
*
* Since: 1.0
*/
typedef enum
{
CLUTTER_ALLOCATION_NONE = 0,
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1,
CLUTTER_DELEGATE_LAYOUT = 1 << 2
} ClutterAllocationFlags;
/** /**
* ClutterAlignAxis: * ClutterAlignAxis:
* @CLUTTER_ALIGN_X_AXIS: Maintain the alignment on the X axis * @CLUTTER_ALIGN_X_AXIS: Maintain the alignment on the X axis
@@ -1317,6 +1343,8 @@ typedef enum
* painting the stages * painting the stages
* @CLUTTER_REPAINT_FLAGS_POST_PAINT: Run the repaint function after * @CLUTTER_REPAINT_FLAGS_POST_PAINT: Run the repaint function after
* painting the stages * painting the stages
* @CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD: Ensure that a new frame
* is queued after adding the repaint function
* *
* Flags to pass to clutter_threads_add_repaint_func_full(). * Flags to pass to clutter_threads_add_repaint_func_full().
* *
@@ -1326,6 +1354,7 @@ typedef enum
{ {
CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0, CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0,
CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1, CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1,
CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD = 1 << 2
} ClutterRepaintFlags; } ClutterRepaintFlags;
/** /**

View File

@@ -2126,42 +2126,6 @@ clutter_event_get_gesture_motion_delta (const ClutterEvent *event,
} }
} }
/**
* clutter_event_get_gesture_motion_delta_unaccelerated:
* @event: A clutter touchpad gesture event
* @dx: (out) (allow-none): the displacement relative to the pointer
* position in the X axis, or %NULL
* @dy: (out) (allow-none): the displacement relative to the pointer
* position in the Y axis, or %NULL
*
* Returns the unaccelerated gesture motion deltas relative to the current
* pointer position. Unlike clutter_event_get_gesture_motion_delta(),
* pointer acceleration is ignored.
**/
void
clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
gdouble *dx,
gdouble *dy)
{
g_return_if_fail (event != NULL);
g_return_if_fail (event->type == CLUTTER_TOUCHPAD_PINCH ||
event->type == CLUTTER_TOUCHPAD_SWIPE);
if (event->type == CLUTTER_TOUCHPAD_PINCH)
{
if (dx)
*dx = event->touchpad_pinch.dx_unaccel;
if (dy)
*dy = event->touchpad_pinch.dy_unaccel;
}
else if (event->type == CLUTTER_TOUCHPAD_SWIPE)
{
if (dx)
*dx = event->touchpad_swipe.dx_unaccel;
if (dy)
*dy = event->touchpad_swipe.dy_unaccel;
}
}
/** /**
* clutter_event_get_scroll_source: * clutter_event_get_scroll_source:
* @event: an scroll event * @event: an scroll event

View File

@@ -431,10 +431,6 @@ struct _ClutterTouchEvent
* @y: the Y coordinate of the pointer, relative to the stage * @y: the Y coordinate of the pointer, relative to the stage
* @dx: movement delta of the pinch focal point in the X axis * @dx: movement delta of the pinch focal point in the X axis
* @dy: movement delta of the pinch focal point in the Y axis * @dy: movement delta of the pinch focal point in the Y axis
* @dx_unaccel: unaccelerated movement delta of the pinch focal
* point in the X axis
* @dy_unaccel: unaccelerated movement delta of the pinch focal
* point in the Y axis
* @angle_delta: angle delta in degrees, clockwise rotations are * @angle_delta: angle delta in degrees, clockwise rotations are
* represented by positive deltas * represented by positive deltas
* @scale: the current scale * @scale: the current scale
@@ -462,8 +458,6 @@ struct _ClutterTouchpadPinchEvent
gfloat y; gfloat y;
gfloat dx; gfloat dx;
gfloat dy; gfloat dy;
gfloat dx_unaccel;
gfloat dy_unaccel;
gfloat angle_delta; gfloat angle_delta;
gfloat scale; gfloat scale;
guint n_fingers; guint n_fingers;
@@ -480,12 +474,8 @@ struct _ClutterTouchpadPinchEvent
* @n_fingers: the number of fingers triggering the swipe * @n_fingers: the number of fingers triggering the swipe
* @x: the X coordinate of the pointer, relative to the stage * @x: the X coordinate of the pointer, relative to the stage
* @y: the Y coordinate of the pointer, relative to the stage * @y: the Y coordinate of the pointer, relative to the stage
* @dx: movement delta of the swipe center point in the X axis * @dx: movement delta of the pinch focal point in the X axis
* @dy: movement delta of the swipe center point in the Y axis * @dy: movement delta of the pinch focal point in the Y axis
* @dx_unaccel: unaccelerated movement delta of the swipe center
* point in the X axis
* @dy_unaccel: unaccelerated movement delta of the swipe center
* point in the Y axis
* *
* Used for touchpad swipe gesture events. The current state of the * Used for touchpad swipe gesture events. The current state of the
* gesture will be determined by the @phase field. * gesture will be determined by the @phase field.
@@ -506,8 +496,6 @@ struct _ClutterTouchpadSwipeEvent
gfloat y; gfloat y;
gfloat dx; gfloat dx;
gfloat dy; gfloat dy;
gfloat dx_unaccel;
gfloat dy_unaccel;
}; };
struct _ClutterPadButtonEvent struct _ClutterPadButtonEvent
@@ -785,11 +773,6 @@ void clutter_event_get_gesture_motion_delta (const Clut
gdouble *dx, gdouble *dx,
gdouble *dy); gdouble *dy);
CLUTTER_EXPORT
void clutter_event_get_gesture_motion_delta_unaccelerated (const ClutterEvent *event,
gdouble *dx,
gdouble *dy);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event); ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event);

View File

@@ -131,7 +131,8 @@ clutter_fixed_layout_get_preferred_height (ClutterLayoutManager *manager,
static void static void
clutter_fixed_layout_allocate (ClutterLayoutManager *manager, clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation) const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{ {
ClutterActor *child; ClutterActor *child;
@@ -139,7 +140,7 @@ clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
child != NULL; child != NULL;
child = clutter_actor_get_next_sibling (child)) child = clutter_actor_get_next_sibling (child))
{ {
clutter_actor_allocate_preferred_size (child); clutter_actor_allocate_preferred_size (child, flags);
} }
} }

View File

@@ -566,7 +566,8 @@ clutter_flow_layout_get_preferred_height (ClutterLayoutManager *manager,
static void static void
clutter_flow_layout_allocate (ClutterLayoutManager *manager, clutter_flow_layout_allocate (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation) const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{ {
ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv; ClutterFlowLayoutPrivate *priv = CLUTTER_FLOW_LAYOUT (manager)->priv;
ClutterActor *actor, *child; ClutterActor *actor, *child;
@@ -728,7 +729,7 @@ clutter_flow_layout_allocate (ClutterLayoutManager *manager,
child_alloc.y1 = ceil (item_y); child_alloc.y1 = ceil (item_y);
child_alloc.x2 = ceil (child_alloc.x1 + item_width); child_alloc.x2 = ceil (child_alloc.x1 + item_width);
child_alloc.y2 = ceil (child_alloc.y1 + item_height); child_alloc.y2 = ceil (child_alloc.y1 + item_height);
clutter_actor_allocate (child, &child_alloc); clutter_actor_allocate (child, &child_alloc, flags);
if (priv->orientation == CLUTTER_FLOW_HORIZONTAL) if (priv->orientation == CLUTTER_FLOW_HORIZONTAL)
item_x = new_x; item_x = new_x;

View File

@@ -1,550 +0,0 @@
/*
* Copyright (C) 2019 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/clutter-frame-clock.h"
#include "clutter/clutter-main.h"
#include "clutter/clutter-private.h"
#include "clutter/clutter-timeline-private.h"
#include "cogl/cogl-trace.h"
enum
{
DESTROY,
N_SIGNALS
};
static guint signals[N_SIGNALS];
/* Wait 2ms after vblank before starting to draw next frame */
#define SYNC_DELAY_US ms2us (2)
typedef struct _ClutterFrameListener
{
const ClutterFrameListenerIface *iface;
gpointer user_data;
} ClutterFrameListener;
typedef struct _ClutterClockSource
{
GSource source;
ClutterFrameClock *frame_clock;
} ClutterClockSource;
typedef enum _ClutterFrameClockState
{
CLUTTER_FRAME_CLOCK_STATE_INIT,
CLUTTER_FRAME_CLOCK_STATE_IDLE,
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
CLUTTER_FRAME_CLOCK_STATE_DISPATCHING,
CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED,
} ClutterFrameClockState;
struct _ClutterFrameClock
{
GObject parent;
float refresh_rate;
ClutterFrameListener listener;
GSource *source;
int64_t frame_count;
ClutterFrameClockState state;
int64_t last_presentation_time_us;
gboolean is_next_presentation_time_valid;
int64_t next_presentation_time_us;
gboolean pending_reschedule;
gboolean pending_reschedule_now;
int inhibit_count;
GList *timelines;
};
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
G_TYPE_OBJECT)
float
clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock)
{
return frame_clock->refresh_rate;
}
void
clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline)
{
gboolean is_first;
if (g_list_find (frame_clock->timelines, timeline))
return;
is_first = !frame_clock->timelines;
frame_clock->timelines = g_list_prepend (frame_clock->timelines, timeline);
if (is_first)
clutter_frame_clock_schedule_update (frame_clock);
}
void
clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline)
{
frame_clock->timelines = g_list_remove (frame_clock->timelines, timeline);
}
static void
advance_timelines (ClutterFrameClock *frame_clock,
int64_t time_us)
{
GList *timelines;
GList *l;
/* we protect ourselves from timelines being removed during
* the advancement by other timelines by copying the list of
* timelines, taking a reference on them, iterating over the
* copied list and then releasing the reference.
*
* we cannot simply take a reference on the timelines and still
* use the list held by the master clock because the do_tick()
* might result in the creation of a new timeline, which gets
* added at the end of the list with no reference increase and
* thus gets disposed at the end of the iteration.
*
* this implies that a newly added timeline will not be advanced
* by this clock iteration, which is perfectly fine since we're
* in its first cycle.
*
* we also cannot steal the frame clock timelines list because
* a timeline might be removed as the direct result of do_tick()
* and remove_timeline() would not find the timeline, failing
* and leaving a dangling pointer behind.
*/
timelines = g_list_copy (frame_clock->timelines);
g_list_foreach (timelines, (GFunc) g_object_ref, NULL);
for (l = timelines; l; l = l->next)
{
ClutterTimeline *timeline = l->data;
_clutter_timeline_do_tick (timeline, time_us / 1000);
}
g_list_free_full (timelines, g_object_unref);
}
static void
maybe_reschedule_update (ClutterFrameClock *frame_clock)
{
if (frame_clock->pending_reschedule ||
frame_clock->timelines)
{
frame_clock->pending_reschedule = FALSE;
if (frame_clock->pending_reschedule_now)
{
frame_clock->pending_reschedule_now = FALSE;
clutter_frame_clock_schedule_update_now (frame_clock);
}
else
{
clutter_frame_clock_schedule_update (frame_clock);
}
}
}
void
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
ClutterFrameInfo *frame_info)
{
int64_t presentation_time_us = frame_info->presentation_time;
if (presentation_time_us > frame_clock->last_presentation_time_us ||
((presentation_time_us - frame_clock->last_presentation_time_us) >
INT64_MAX / 2))
{
frame_clock->last_presentation_time_us = presentation_time_us;
}
else
{
g_warning_once ("Bogus presentation time %" G_GINT64_FORMAT
" travelled back in time, using current time.",
presentation_time_us);
frame_clock->last_presentation_time_us = g_get_monotonic_time ();
}
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
g_warn_if_reached ();
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
maybe_reschedule_update (frame_clock);
break;
}
}
static void
calculate_next_update_time_us (ClutterFrameClock *frame_clock,
int64_t *out_next_update_time_us,
int64_t *out_next_presentation_time_us)
{
int64_t last_presentation_time_us;
int64_t now_us;
float refresh_rate;
int64_t refresh_interval_us;
int64_t min_render_time_allowed_us;
int64_t max_render_time_allowed_us;
int64_t last_next_presentation_time_us;
int64_t time_since_last_next_presentation_time_us;
int64_t next_presentation_time_us;
int64_t next_update_time_us;
now_us = g_get_monotonic_time ();
refresh_rate = frame_clock->refresh_rate;
refresh_interval_us = (int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
min_render_time_allowed_us = refresh_interval_us / 2;
max_render_time_allowed_us = refresh_interval_us - SYNC_DELAY_US;
if (min_render_time_allowed_us > max_render_time_allowed_us)
min_render_time_allowed_us = max_render_time_allowed_us;
last_presentation_time_us = frame_clock->last_presentation_time_us;
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
/* Skip ahead to get close to the actual next presentation time. */
if (next_presentation_time_us < now_us)
{
int64_t logical_clock_offset_us;
int64_t logical_clock_phase_us;
int64_t hw_clock_offset_us;
logical_clock_offset_us = now_us % refresh_interval_us;
logical_clock_phase_us = now_us - logical_clock_offset_us;
hw_clock_offset_us = last_presentation_time_us % refresh_interval_us;
next_presentation_time_us = logical_clock_phase_us + hw_clock_offset_us;
}
/* Skip one interval if we got an early presented event. */
last_next_presentation_time_us = frame_clock->next_presentation_time_us;
time_since_last_next_presentation_time_us =
next_presentation_time_us - last_next_presentation_time_us;
if (frame_clock->is_next_presentation_time_valid &&
time_since_last_next_presentation_time_us < (refresh_interval_us / 2))
{
next_presentation_time_us =
frame_clock->next_presentation_time_us + refresh_interval_us;
}
while (next_presentation_time_us < now_us + min_render_time_allowed_us)
next_presentation_time_us += refresh_interval_us;
next_update_time_us = next_presentation_time_us - max_render_time_allowed_us;
*out_next_update_time_us = next_update_time_us;
*out_next_presentation_time_us = next_presentation_time_us;
}
void
clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
{
frame_clock->inhibit_count++;
if (frame_clock->inhibit_count == 1)
{
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
frame_clock->pending_reschedule = TRUE;
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
break;
}
g_source_set_ready_time (frame_clock->source, -1);
}
}
void
clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock)
{
g_return_if_fail (frame_clock->inhibit_count > 0);
frame_clock->inhibit_count--;
if (frame_clock->inhibit_count == 0)
maybe_reschedule_update (frame_clock);
}
void
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
{
int64_t next_update_time_us = -1;
if (frame_clock->inhibit_count > 0)
{
frame_clock->pending_reschedule = TRUE;
frame_clock->pending_reschedule_now = TRUE;
return;
}
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
next_update_time_us = g_get_monotonic_time ();
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
return;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->pending_reschedule = TRUE;
frame_clock->pending_reschedule_now = TRUE;
return;
}
g_warn_if_fail (next_update_time_us != -1);
g_source_set_ready_time (frame_clock->source, next_update_time_us);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
frame_clock->is_next_presentation_time_valid = FALSE;
}
void
clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
{
int64_t next_update_time_us = -1;
if (frame_clock->inhibit_count > 0)
{
frame_clock->pending_reschedule = TRUE;
return;
}
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
next_update_time_us = g_get_monotonic_time ();
break;
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
calculate_next_update_time_us (frame_clock,
&next_update_time_us,
&frame_clock->next_presentation_time_us);
frame_clock->is_next_presentation_time_valid = TRUE;
break;
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
return;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
frame_clock->pending_reschedule = TRUE;
return;
}
g_warn_if_fail (next_update_time_us != -1);
g_source_set_ready_time (frame_clock->source, next_update_time_us);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
}
static void
clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
int64_t time_us)
{
int64_t frame_count;
ClutterFrameResult result;
COGL_TRACE_BEGIN_SCOPED (ClutterFrameCLockDispatch, "Frame Clock (dispatch)");
g_source_set_ready_time (frame_clock->source, -1);
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
frame_count = frame_clock->frame_count++;
COGL_TRACE_BEGIN (ClutterFrameClockEvents, "Frame Clock (before frame)");
if (frame_clock->listener.iface->before_frame)
{
frame_clock->listener.iface->before_frame (frame_clock,
frame_count,
frame_clock->listener.user_data);
}
COGL_TRACE_END (ClutterFrameClockEvents);
COGL_TRACE_BEGIN (ClutterFrameClockTimelines, "Frame Clock (timelines)");
advance_timelines (frame_clock, time_us);
COGL_TRACE_END (ClutterFrameClockTimelines);
COGL_TRACE_BEGIN (ClutterFrameClockFrame, "Frame Clock (frame)");
result = frame_clock->listener.iface->frame (frame_clock,
frame_count,
time_us,
frame_clock->listener.user_data);
COGL_TRACE_END (ClutterFrameClockFrame);
switch (frame_clock->state)
{
case CLUTTER_FRAME_CLOCK_STATE_INIT:
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
g_warn_if_reached ();
break;
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
break;
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
switch (result)
{
case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED;
break;
case CLUTTER_FRAME_RESULT_IDLE:
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
maybe_reschedule_update (frame_clock);
break;
}
break;
}
}
static gboolean
frame_clock_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterFrameClock *frame_clock = clock_source->frame_clock;
int64_t dispatch_time_us;
dispatch_time_us = g_source_get_time (source);
clutter_frame_clock_dispatch (frame_clock, dispatch_time_us);
return G_SOURCE_CONTINUE;
}
static GSourceFuncs frame_clock_source_funcs = {
NULL,
NULL,
frame_clock_source_dispatch,
NULL
};
static void
init_frame_clock_source (ClutterFrameClock *frame_clock)
{
GSource *source;
ClutterClockSource *clock_source;
g_autofree char *name = NULL;
source = g_source_new (&frame_clock_source_funcs, sizeof (ClutterClockSource));
clock_source = (ClutterClockSource *) source;
name = g_strdup_printf ("Clutter frame clock (%p)", frame_clock);
g_source_set_name (source, name);
g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
g_source_set_can_recurse (source, FALSE);
clock_source->frame_clock = frame_clock;
frame_clock->source = source;
g_source_attach (source, NULL);
}
ClutterFrameClock *
clutter_frame_clock_new (float refresh_rate,
const ClutterFrameListenerIface *iface,
gpointer user_data)
{
ClutterFrameClock *frame_clock;
g_assert_cmpfloat (refresh_rate, >, 0.0);
frame_clock = g_object_new (CLUTTER_TYPE_FRAME_CLOCK, NULL);
frame_clock->listener.iface = iface;
frame_clock->listener.user_data = user_data;
init_frame_clock_source (frame_clock);
frame_clock->refresh_rate = refresh_rate;
return frame_clock;
}
void
clutter_frame_clock_destroy (ClutterFrameClock *frame_clock)
{
g_object_run_dispose (G_OBJECT (frame_clock));
g_object_unref (frame_clock);
}
static void
clutter_frame_clock_dispose (GObject *object)
{
ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object);
if (frame_clock->source)
{
g_signal_emit (frame_clock, signals[DESTROY], 0);
g_source_destroy (frame_clock->source);
g_clear_pointer (&frame_clock->source, g_source_unref);
}
G_OBJECT_CLASS (clutter_frame_clock_parent_class)->dispose (object);
}
static void
clutter_frame_clock_init (ClutterFrameClock *frame_clock)
{
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_INIT;
}
static void
clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = clutter_frame_clock_dispose;
signals[DESTROY] =
g_signal_new (I_("destroy"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE,
0);
}

View File

@@ -1,87 +0,0 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_FRAME_CLOCK_H
#define CLUTTER_FRAME_CLOCK_H
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <glib.h>
#include <glib-object.h>
#include <stdint.h>
#include "clutter/clutter-types.h"
typedef enum _ClutterFrameResult
{
CLUTTER_FRAME_RESULT_PENDING_PRESENTED,
CLUTTER_FRAME_RESULT_IDLE,
} ClutterFrameResult;
#define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ())
CLUTTER_EXPORT
G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
CLUTTER, FRAME_CLOCK,
GObject)
typedef struct _ClutterFrameListenerIface
{
void (* before_frame) (ClutterFrameClock *frame_clock,
int64_t frame_count,
gpointer user_data);
ClutterFrameResult (* frame) (ClutterFrameClock *frame_clock,
int64_t frame_count,
int64_t time_us,
gpointer user_data);
} ClutterFrameListenerIface;
CLUTTER_EXPORT
ClutterFrameClock * clutter_frame_clock_new (float refresh_rate,
const ClutterFrameListenerIface *iface,
gpointer user_data);
CLUTTER_EXPORT
void clutter_frame_clock_destroy (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
ClutterFrameInfo *frame_info);
CLUTTER_EXPORT
void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock);
CLUTTER_EXPORT
void clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock);
void clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline);
void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
ClutterTimeline *timeline);
CLUTTER_EXPORT
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
#endif /* CLUTTER_FRAME_CLOCK_H */

View File

@@ -157,8 +157,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (ClutterGestureAction, clutter_gesture_action, CLUTTE
static GesturePoint * static GesturePoint *
gesture_register_point (ClutterGestureAction *action, ClutterEvent *event) gesture_register_point (ClutterGestureAction *action, ClutterEvent *event)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
GesturePoint *point = NULL; GesturePoint *point = NULL;
if (priv->points->len >= MAX_GESTURE_POINTS) if (priv->points->len >= MAX_GESTURE_POINTS)
@@ -191,8 +190,7 @@ gesture_find_point (ClutterGestureAction *action,
ClutterEvent *event, ClutterEvent *event,
gint *position) gint *position)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
GesturePoint *point = NULL; GesturePoint *point = NULL;
ClutterEventType type = clutter_event_type (event); ClutterEventType type = clutter_event_type (event);
ClutterInputDevice *device = clutter_event_get_device (event); ClutterInputDevice *device = clutter_event_get_device (event);
@@ -222,10 +220,9 @@ gesture_find_point (ClutterGestureAction *action,
static void static void
gesture_unregister_point (ClutterGestureAction *action, gint position) gesture_unregister_point (ClutterGestureAction *action, gint position)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
if (priv->points->len == 0) if (action->priv->points->len == 0)
return; return;
g_array_remove_index (priv->points, position); g_array_remove_index (priv->points, position);
@@ -306,8 +303,7 @@ gesture_point_unset (GesturePoint *point)
static void static void
cancel_gesture (ClutterGestureAction *action) cancel_gesture (ClutterGestureAction *action)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
ClutterActor *actor; ClutterActor *actor;
priv->in_gesture = FALSE; priv->in_gesture = FALSE;
@@ -317,15 +313,14 @@ cancel_gesture (ClutterGestureAction *action)
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor); g_signal_emit (action, gesture_signals[GESTURE_CANCEL], 0, actor);
g_array_set_size (priv->points, 0); g_array_set_size (action->priv->points, 0);
} }
static gboolean static gboolean
begin_gesture (ClutterGestureAction *action, begin_gesture (ClutterGestureAction *action,
ClutterActor *actor) ClutterActor *actor)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
gboolean return_value; gboolean return_value;
priv->in_gesture = TRUE; priv->in_gesture = TRUE;
@@ -358,8 +353,7 @@ stage_captured_event_cb (ClutterActor *stage,
ClutterEvent *event, ClutterEvent *event,
ClutterGestureAction *action) ClutterGestureAction *action)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
ClutterActor *actor; ClutterActor *actor;
gint position; gint position;
float threshold_x, threshold_y; float threshold_x, threshold_y;
@@ -494,8 +488,7 @@ actor_captured_event_cb (ClutterActor *actor,
ClutterEvent *event, ClutterEvent *event,
ClutterGestureAction *action) ClutterGestureAction *action)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = action->priv;
clutter_gesture_action_get_instance_private (action);
GesturePoint *point G_GNUC_UNUSED; GesturePoint *point G_GNUC_UNUSED;
if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) && if ((clutter_event_type (event) != CLUTTER_BUTTON_PRESS) &&
@@ -529,8 +522,7 @@ static void
clutter_gesture_action_set_actor (ClutterActorMeta *meta, clutter_gesture_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor) ClutterActor *actor)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (meta)->priv;
clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (meta));
ClutterActorMetaClass *meta_class = ClutterActorMetaClass *meta_class =
CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class); CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);
@@ -564,22 +556,6 @@ clutter_gesture_action_set_actor (ClutterActorMeta *meta,
meta_class->set_actor (meta, actor); meta_class->set_actor (meta, actor);
} }
static void
clutter_gesture_action_set_enabled (ClutterActorMeta *meta,
gboolean is_enabled)
{
ClutterActorMetaClass *meta_class =
CLUTTER_ACTOR_META_CLASS (clutter_gesture_action_parent_class);
ClutterGestureAction *gesture_action = CLUTTER_GESTURE_ACTION (meta);
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (gesture_action);
if (!is_enabled && priv->in_gesture)
cancel_gesture (gesture_action);
meta_class->set_enabled (meta, is_enabled);
}
static gboolean static gboolean
default_event_handler (ClutterGestureAction *action, default_event_handler (ClutterGestureAction *action,
ClutterActor *actor) ClutterActor *actor)
@@ -594,8 +570,6 @@ clutter_gesture_action_set_property (GObject *gobject,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject); ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);
ClutterGestureActionPrivate *priv =
clutter_gesture_action_get_instance_private (self);
switch (prop_id) switch (prop_id)
{ {
@@ -608,15 +582,11 @@ clutter_gesture_action_set_property (GObject *gobject,
break; break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_X: case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
clutter_gesture_action_set_threshold_trigger_distance (self, clutter_gesture_action_set_threshold_trigger_distance (self, g_value_get_float (value), self->priv->distance_y);
g_value_get_float (value),
priv->distance_y);
break; break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_Y: case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
clutter_gesture_action_set_threshold_trigger_distance (self, clutter_gesture_action_set_threshold_trigger_distance (self, self->priv->distance_x, g_value_get_float (value));
priv->distance_x,
g_value_get_float (value));
break; break;
default: default:
@@ -631,29 +601,28 @@ clutter_gesture_action_get_property (GObject *gobject,
GValue *value, GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureAction *self = CLUTTER_GESTURE_ACTION (gobject);
clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (gobject));
switch (prop_id) switch (prop_id)
{ {
case PROP_N_TOUCH_POINTS: case PROP_N_TOUCH_POINTS:
g_value_set_int (value, priv->requested_nb_points); g_value_set_int (value, self->priv->requested_nb_points);
break; break;
case PROP_THRESHOLD_TRIGGER_EDGE: case PROP_THRESHOLD_TRIGGER_EDGE:
g_value_set_enum (value, priv->edge); g_value_set_enum (value, self->priv->edge);
break; break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_X: case PROP_THRESHOLD_TRIGGER_DISTANCE_X:
if (priv->distance_x > 0.0) if (self->priv->distance_x > 0.0)
g_value_set_float (value, priv->distance_x); g_value_set_float (value, self->priv->distance_x);
else else
g_value_set_float (value, gesture_get_default_threshold ()); g_value_set_float (value, gesture_get_default_threshold ());
break; break;
case PROP_THRESHOLD_TRIGGER_DISTANCE_Y: case PROP_THRESHOLD_TRIGGER_DISTANCE_Y:
if (priv->distance_y > 0.0) if (self->priv->distance_y > 0.0)
g_value_set_float (value, priv->distance_y); g_value_set_float (value, self->priv->distance_y);
else else
g_value_set_float (value, gesture_get_default_threshold ()); g_value_set_float (value, gesture_get_default_threshold ());
break; break;
@@ -667,8 +636,7 @@ clutter_gesture_action_get_property (GObject *gobject,
static void static void
clutter_gesture_action_finalize (GObject *gobject) clutter_gesture_action_finalize (GObject *gobject)
{ {
ClutterGestureActionPrivate *priv = ClutterGestureActionPrivate *priv = CLUTTER_GESTURE_ACTION (gobject)->priv;
clutter_gesture_action_get_instance_private (CLUTTER_GESTURE_ACTION (gobject));
g_array_unref (priv->points); g_array_unref (priv->points);
@@ -686,7 +654,6 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
gobject_class->get_property = clutter_gesture_action_get_property; gobject_class->get_property = clutter_gesture_action_get_property;
meta_class->set_actor = clutter_gesture_action_set_actor; meta_class->set_actor = clutter_gesture_action_set_actor;
meta_class->set_enabled = clutter_gesture_action_set_enabled;
klass->gesture_begin = default_event_handler; klass->gesture_begin = default_event_handler;
klass->gesture_progress = default_event_handler; klass->gesture_progress = default_event_handler;
@@ -860,14 +827,13 @@ clutter_gesture_action_class_init (ClutterGestureActionClass *klass)
static void static void
clutter_gesture_action_init (ClutterGestureAction *self) clutter_gesture_action_init (ClutterGestureAction *self)
{ {
ClutterGestureActionPrivate *priv = self->priv = clutter_gesture_action_get_instance_private (self);
clutter_gesture_action_get_instance_private (self);
priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3); self->priv->points = g_array_sized_new (FALSE, TRUE, sizeof (GesturePoint), 3);
g_array_set_clear_func (priv->points, (GDestroyNotify) gesture_point_unset); g_array_set_clear_func (self->priv->points, (GDestroyNotify) gesture_point_unset);
priv->requested_nb_points = 1; self->priv->requested_nb_points = 1;
priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_NONE; self->priv->edge = CLUTTER_GESTURE_TRIGGER_EDGE_NONE;
} }
/** /**
@@ -906,21 +872,16 @@ clutter_gesture_action_get_press_coords (ClutterGestureAction *action,
gfloat *press_x, gfloat *press_x,
gfloat *press_y) gfloat *press_y)
{ {
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
g_return_if_fail (action->priv->points->len > point);
priv = clutter_gesture_action_get_instance_private (action);
g_return_if_fail (priv->points->len > point);
if (press_x) if (press_x)
*press_x = g_array_index (priv->points, *press_x = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).press_x; point).press_x;
if (press_y) if (press_y)
*press_y = g_array_index (priv->points, *press_y = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).press_y; point).press_y;
} }
@@ -946,21 +907,16 @@ clutter_gesture_action_get_motion_coords (ClutterGestureAction *action,
gfloat *motion_x, gfloat *motion_x,
gfloat *motion_y) gfloat *motion_y)
{ {
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
g_return_if_fail (action->priv->points->len > point);
priv = clutter_gesture_action_get_instance_private (action);
g_return_if_fail (priv->points->len > point);
if (motion_x) if (motion_x)
*motion_x = g_array_index (priv->points, *motion_x = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).last_motion_x; point).last_motion_x;
if (motion_y) if (motion_y)
*motion_y = g_array_index (priv->points, *motion_y = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).last_motion_y; point).last_motion_y;
} }
@@ -988,19 +944,15 @@ clutter_gesture_action_get_motion_delta (ClutterGestureAction *action,
gfloat *delta_x, gfloat *delta_x,
gfloat *delta_y) gfloat *delta_y)
{ {
ClutterGestureActionPrivate *priv;
gfloat d_x, d_y; gfloat d_x, d_y;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
g_return_val_if_fail (action->priv->points->len > point, 0);
priv = clutter_gesture_action_get_instance_private (action); d_x = g_array_index (action->priv->points,
g_return_val_if_fail (priv->points->len > point, 0);
d_x = g_array_index (priv->points,
GesturePoint, GesturePoint,
point).last_delta_x; point).last_delta_x;
d_y = g_array_index (priv->points, d_y = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).last_delta_y; point).last_delta_y;
@@ -1034,21 +986,16 @@ clutter_gesture_action_get_release_coords (ClutterGestureAction *action,
gfloat *release_x, gfloat *release_x,
gfloat *release_y) gfloat *release_y)
{ {
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
g_return_if_fail (action->priv->points->len > point);
priv = clutter_gesture_action_get_instance_private (action);
g_return_if_fail (priv->points->len > point);
if (release_x) if (release_x)
*release_x = g_array_index (priv->points, *release_x = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).release_x; point).release_x;
if (release_y) if (release_y)
*release_y = g_array_index (priv->points, *release_y = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).release_y; point).release_y;
} }
@@ -1074,20 +1021,16 @@ clutter_gesture_action_get_velocity (ClutterGestureAction *action,
gfloat *velocity_x, gfloat *velocity_x,
gfloat *velocity_y) gfloat *velocity_y)
{ {
ClutterGestureActionPrivate *priv;
gfloat d_x, d_y, distance, velocity; gfloat d_x, d_y, distance, velocity;
gint64 d_t; gint64 d_t;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
g_return_val_if_fail (action->priv->points->len > point, 0);
priv = clutter_gesture_action_get_instance_private (action);
g_return_val_if_fail (priv->points->len > point, 0);
distance = clutter_gesture_action_get_motion_delta (action, point, distance = clutter_gesture_action_get_motion_delta (action, point,
&d_x, &d_y); &d_x, &d_y);
d_t = g_array_index (priv->points, d_t = g_array_index (action->priv->points,
GesturePoint, GesturePoint,
point).last_delta_time; point).last_delta_time;
@@ -1114,13 +1057,9 @@ clutter_gesture_action_get_velocity (ClutterGestureAction *action,
gint gint
clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action) clutter_gesture_action_get_n_touch_points (ClutterGestureAction *action)
{ {
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
priv = clutter_gesture_action_get_instance_private (action); return action->priv->requested_nb_points;
return priv->requested_nb_points;
} }
/** /**
@@ -1141,7 +1080,7 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
g_return_if_fail (nb_points >= 1); g_return_if_fail (nb_points >= 1);
priv = clutter_gesture_action_get_instance_private (action); priv = action->priv;
if (priv->requested_nb_points == nb_points) if (priv->requested_nb_points == nb_points)
return; return;
@@ -1195,13 +1134,9 @@ clutter_gesture_action_set_n_touch_points (ClutterGestureAction *action,
guint guint
clutter_gesture_action_get_n_current_points (ClutterGestureAction *action) clutter_gesture_action_get_n_current_points (ClutterGestureAction *action)
{ {
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), 0);
priv = clutter_gesture_action_get_instance_private (action); return action->priv->points->len;
return priv->points->len;
} }
/** /**
@@ -1219,15 +1154,10 @@ ClutterEventSequence *
clutter_gesture_action_get_sequence (ClutterGestureAction *action, clutter_gesture_action_get_sequence (ClutterGestureAction *action,
guint point) guint point)
{ {
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
g_return_val_if_fail (action->priv->points->len > point, NULL);
priv = clutter_gesture_action_get_instance_private (action); return g_array_index (action->priv->points, GesturePoint, point).sequence;
g_return_val_if_fail (priv->points->len > point, NULL);
return g_array_index (priv->points, GesturePoint, point).sequence;
} }
/** /**
@@ -1246,15 +1176,10 @@ ClutterInputDevice *
clutter_gesture_action_get_device (ClutterGestureAction *action, clutter_gesture_action_get_device (ClutterGestureAction *action,
guint point) guint point)
{ {
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
g_return_val_if_fail (action->priv->points->len > point, NULL);
priv = clutter_gesture_action_get_instance_private (action); return g_array_index (action->priv->points, GesturePoint, point).device;
g_return_val_if_fail (priv->points->len > point, NULL);
return g_array_index (priv->points, GesturePoint, point).device;
} }
/** /**
@@ -1274,15 +1199,11 @@ clutter_gesture_action_get_last_event (ClutterGestureAction *action,
guint point) guint point)
{ {
GesturePoint *gesture_point; GesturePoint *gesture_point;
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL); g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), NULL);
g_return_val_if_fail (action->priv->points->len > point, NULL);
priv = clutter_gesture_action_get_instance_private (action); gesture_point = &g_array_index (action->priv->points, GesturePoint, point);
g_return_val_if_fail (priv->points->len > point, NULL);
gesture_point = &g_array_index (priv->points, GesturePoint, point);
return gesture_point->last_event; return gesture_point->last_event;
} }
@@ -1319,16 +1240,12 @@ void
clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action, clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *action,
ClutterGestureTriggerEdge edge) ClutterGestureTriggerEdge edge)
{ {
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action); if (action->priv->edge == edge)
if (priv->edge == edge)
return; return;
priv->edge = edge; action->priv->edge = edge;
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_EDGE]); g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_EDGE]);
} }
@@ -1347,14 +1264,10 @@ clutter_gesture_action_set_threshold_trigger_edge (ClutterGestureAction *ac
ClutterGestureTriggerEdge ClutterGestureTriggerEdge
clutter_gesture_action_get_threshold_trigger_edge (ClutterGestureAction *action) clutter_gesture_action_get_threshold_trigger_edge (ClutterGestureAction *action)
{ {
ClutterGestureActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action), g_return_val_if_fail (CLUTTER_IS_GESTURE_ACTION (action),
CLUTTER_GESTURE_TRIGGER_EDGE_NONE); CLUTTER_GESTURE_TRIGGER_EDGE_NONE);
priv = clutter_gesture_action_get_instance_private (action); return action->priv->edge;
return priv->edge;
} }
/** /**
@@ -1394,21 +1307,17 @@ clutter_gesture_action_set_threshold_trigger_distance (ClutterGestureAction
float x, float x,
float y) float y)
{ {
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action); if (fabsf (x - action->priv->distance_x) > FLOAT_EPSILON)
if (fabsf (x - priv->distance_x) > FLOAT_EPSILON)
{ {
priv->distance_x = x; action->priv->distance_x = x;
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]); g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_X]);
} }
if (fabsf (y - priv->distance_y) > FLOAT_EPSILON) if (fabsf (y - action->priv->distance_y) > FLOAT_EPSILON)
{ {
priv->distance_y = y; action->priv->distance_y = y;
g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y]); g_object_notify_by_pspec (G_OBJECT (action), gesture_props[PROP_THRESHOLD_TRIGGER_DISTANCE_Y]);
} }
} }
@@ -1429,23 +1338,19 @@ clutter_gesture_action_get_threshold_trigger_distance (ClutterGestureAction *act
float *x, float *x,
float *y) float *y)
{ {
ClutterGestureActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action)); g_return_if_fail (CLUTTER_IS_GESTURE_ACTION (action));
priv = clutter_gesture_action_get_instance_private (action);
if (x != NULL) if (x != NULL)
{ {
if (priv->distance_x > 0.0) if (action->priv->distance_x > 0.0)
*x = priv->distance_x; *x = action->priv->distance_x;
else else
*x = gesture_get_default_threshold (); *x = gesture_get_default_threshold ();
} }
if (y != NULL) if (y != NULL)
{ {
if (priv->distance_y > 0.0) if (action->priv->distance_y > 0.0)
*y = priv->distance_y; *y = action->priv->distance_y;
else else
*y = gesture_get_default_threshold (); *y = gesture_get_default_threshold ();
} }

View File

@@ -34,13 +34,32 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define CLUTTER_TYPE_GESTURE_ACTION (clutter_gesture_action_get_type ()) #define CLUTTER_TYPE_GESTURE_ACTION (clutter_gesture_action_get_type ())
#define CLUTTER_GESTURE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureAction))
#define CLUTTER_IS_GESTURE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GESTURE_ACTION))
#define CLUTTER_GESTURE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureActionClass))
#define CLUTTER_IS_GESTURE_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GESTURE_ACTION))
#define CLUTTER_GESTURE_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GESTURE_ACTION, ClutterGestureActionClass))
CLUTTER_EXPORT typedef struct _ClutterGestureAction ClutterGestureAction;
G_DECLARE_DERIVABLE_TYPE (ClutterGestureAction, clutter_gesture_action, typedef struct _ClutterGestureActionPrivate ClutterGestureActionPrivate;
CLUTTER, GESTURE_ACTION, ClutterAction); typedef struct _ClutterGestureActionClass ClutterGestureActionClass;
typedef struct _ClutterGestureActionPrivate ClutterGestureActionPrivate; /**
* ClutterGestureAction:
*
* The #ClutterGestureAction structure contains
* only private data and should be accessed using the provided API
*
* Since: 1.8
*/
struct _ClutterGestureAction
{
/*< private >*/
ClutterAction parent_instance;
ClutterGestureActionPrivate *priv;
};
/** /**
* ClutterGestureActionClass: * ClutterGestureActionClass:
@@ -82,6 +101,9 @@ struct _ClutterGestureActionClass
void (* _clutter_gesture_action6) (void); void (* _clutter_gesture_action6) (void);
}; };
CLUTTER_EXPORT
GType clutter_gesture_action_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterAction * clutter_gesture_action_new (void); ClutterAction * clutter_gesture_action_new (void);

View File

@@ -1391,7 +1391,8 @@ allocate_child (ClutterGridRequest *request,
static void static void
clutter_grid_layout_allocate (ClutterLayoutManager *layout, clutter_grid_layout_allocate (ClutterLayoutManager *layout,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation) const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{ {
ClutterGridLayout *self = CLUTTER_GRID_LAYOUT (layout); ClutterGridLayout *self = CLUTTER_GRID_LAYOUT (layout);
ClutterOrientation orientation; ClutterOrientation orientation;
@@ -1452,7 +1453,7 @@ clutter_grid_layout_allocate (ClutterLayoutManager *layout,
child_allocation.x2 = child_allocation.x1 + width; child_allocation.x2 = child_allocation.x1 + width;
child_allocation.y2 = child_allocation.y1 + height; child_allocation.y2 = child_allocation.y1 + height;
clutter_actor_allocate (child, &child_allocation); clutter_actor_allocate (child, &child_allocation, flags);
} }
} }

View File

@@ -0,0 +1,96 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2006 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CLUTTER_GROUP_H__
#define __CLUTTER_GROUP_H__
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <glib-object.h>
#include <clutter/clutter-types.h>
#include <clutter/clutter-actor.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_GROUP (clutter_group_get_type ())
#define CLUTTER_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GROUP, ClutterGroup))
#define CLUTTER_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GROUP, ClutterGroupClass))
#define CLUTTER_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GROUP))
#define CLUTTER_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GROUP))
#define CLUTTER_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GROUP, ClutterGroupClass))
/* XXX - ClutterGroup is to be considered fully deprecated; the only
* reason we keep this header is because ClutterStage inherits from
* ClutterGroup, and thus we need to have a structure definition for
* the Stage object to expand.
*/
typedef struct _ClutterGroup ClutterGroup;
typedef struct _ClutterGroupClass ClutterGroupClass;
typedef struct _ClutterGroupPrivate ClutterGroupPrivate;
/**
* ClutterGroup:
*
* The #ClutterGroup structure contains only private data
* and should be accessed using the provided API
*
* Since: 0.2
*/
struct _ClutterGroup
{
/*< private >*/
ClutterActor parent_instance;
ClutterGroupPrivate *priv;
};
/**
* ClutterGroupClass:
*
* The #ClutterGroupClass structure contains only private data
*
* Since: 0.2
*/
struct _ClutterGroupClass
{
/*< private >*/
ClutterActorClass parent_class;
/* padding for future expansion */
void (*_clutter_reserved1) (void);
void (*_clutter_reserved2) (void);
void (*_clutter_reserved3) (void);
void (*_clutter_reserved4) (void);
void (*_clutter_reserved5) (void);
void (*_clutter_reserved6) (void);
};
CLUTTER_EXPORT
GType clutter_group_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __CLUTTER_GROUP_H__ */

View File

@@ -692,6 +692,20 @@ _clutter_input_device_free_touch_info (gpointer data)
g_slice_free (ClutterTouchInfo, data); g_slice_free (ClutterTouchInfo, data);
} }
static ClutterActor *
_clutter_input_device_get_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence)
{
ClutterTouchInfo *info;
if (sequence == NULL)
return device->cursor_actor;
info = g_hash_table_lookup (device->touch_sequences_info, sequence);
return info->actor;
}
static void static void
_clutter_input_device_associate_actor (ClutterInputDevice *device, _clutter_input_device_associate_actor (ClutterInputDevice *device,
ClutterEventSequence *sequence, ClutterEventSequence *sequence,
@@ -801,7 +815,7 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
ClutterActor *actor, ClutterActor *actor,
gboolean emit_crossing) gboolean emit_crossing)
{ {
ClutterActor *old_actor = clutter_input_device_get_actor (device, sequence); ClutterActor *old_actor = _clutter_input_device_get_actor (device, sequence);
if (old_actor == actor) if (old_actor == actor)
return; return;
@@ -836,7 +850,7 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
} }
/* processing the event might have destroyed the actor */ /* processing the event might have destroyed the actor */
tmp_old_actor = clutter_input_device_get_actor (device, sequence); tmp_old_actor = _clutter_input_device_get_actor (device, sequence);
_clutter_input_device_unassociate_actor (device, _clutter_input_device_unassociate_actor (device,
old_actor, old_actor,
tmp_old_actor == NULL); tmp_old_actor == NULL);
@@ -1040,7 +1054,7 @@ clutter_input_device_update (ClutterInputDevice *device,
clutter_input_device_get_coords (device, sequence, &point); clutter_input_device_get_coords (device, sequence, &point);
old_cursor_actor = clutter_input_device_get_actor (device, sequence); old_cursor_actor = _clutter_input_device_get_actor (device, sequence);
new_cursor_actor = new_cursor_actor =
_clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE); _clutter_stage_do_pick (stage, point.x, point.y, CLUTTER_PICK_REACTIVE);
@@ -1071,33 +1085,22 @@ clutter_input_device_update (ClutterInputDevice *device,
} }
/** /**
* clutter_input_device_get_actor: * clutter_input_device_get_pointer_actor:
* @device: a #ClutterInputDevice * @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
* @sequence: (allow-none): an optional #ClutterEventSequence
* *
* Retrieves the #ClutterActor underneath the pointer or touchpoint * Retrieves the #ClutterActor underneath the pointer of @device
* of @device and @sequence.
* *
* Return value: (transfer none): a pointer to the #ClutterActor or %NULL * Return value: (transfer none): a pointer to the #ClutterActor or %NULL
* *
* Since: 1.2 * Since: 1.2
*/ */
ClutterActor * ClutterActor *
clutter_input_device_get_actor (ClutterInputDevice *device, clutter_input_device_get_pointer_actor (ClutterInputDevice *device)
ClutterEventSequence *sequence)
{ {
ClutterTouchInfo *info;
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
if (sequence == NULL) return device->cursor_actor;
return device->cursor_actor;
info = g_hash_table_lookup (device->touch_sequences_info, sequence);
g_return_val_if_fail (info != NULL, NULL);
return info->actor;
} }
/** /**

View File

@@ -92,8 +92,7 @@ gboolean clutter_input_device_get_coords (ClutterInputDevi
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device); ClutterModifierType clutter_input_device_get_modifier_state (ClutterInputDevice *device);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterActor * clutter_input_device_get_actor (ClutterInputDevice *device, ClutterActor * clutter_input_device_get_pointer_actor (ClutterInputDevice *device);
ClutterEventSequence *sequence);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device); ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
CLUTTER_EXPORT CLUTTER_EXPORT

View File

@@ -37,6 +37,9 @@
* any object taking a reference on a #ClutterInterval instance should * any object taking a reference on a #ClutterInterval instance should
* also take ownership of the interval by using g_object_ref_sink(). * also take ownership of the interval by using g_object_ref_sink().
* *
* #ClutterInterval is used by #ClutterAnimation to define the
* interval of values that an implicit animation should tween over.
*
* #ClutterInterval can be subclassed to override the validation * #ClutterInterval can be subclassed to override the validation
* and value computation. * and value computation.
* *

View File

@@ -32,7 +32,8 @@
* it has been paired, and it controls the allocation of its children. * it has been paired, and it controls the allocation of its children.
* *
* Any composite or container #ClutterActor subclass can delegate the * Any composite or container #ClutterActor subclass can delegate the
* layouting of its children to a #ClutterLayoutManager. * layouting of its children to a #ClutterLayoutManager. Clutter provides
* a generic container using #ClutterLayoutManager called #ClutterBox.
* *
* Clutter provides some simple #ClutterLayoutManager sub-classes, like * Clutter provides some simple #ClutterLayoutManager sub-classes, like
* #ClutterFlowLayout and #ClutterBinLayout. * #ClutterFlowLayout and #ClutterBinLayout.
@@ -96,7 +97,7 @@
* *
* |[ * |[
* { * {
* "type" : "ClutterActor", * "type" : "ClutterBox",
* "layout-manager" : { "type" : "ClutterGridLayout" }, * "layout-manager" : { "type" : "ClutterGridLayout" },
* "children" : [ * "children" : [
* { * {
@@ -135,6 +136,7 @@
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-container.h" #include "deprecated/clutter-container.h"
#include "deprecated/clutter-alpha.h"
#include "clutter-debug.h" #include "clutter-debug.h"
#include "clutter-layout-manager.h" #include "clutter-layout-manager.h"
@@ -162,6 +164,7 @@ G_DEFINE_ABSTRACT_TYPE (ClutterLayoutManager,
G_TYPE_INITIALLY_UNOWNED) G_TYPE_INITIALLY_UNOWNED)
static GQuark quark_layout_meta = 0; static GQuark quark_layout_meta = 0;
static GQuark quark_layout_alpha = 0;
static guint manager_signals[LAST_SIGNAL] = { 0, }; static guint manager_signals[LAST_SIGNAL] = { 0, };
@@ -252,7 +255,8 @@ layout_manager_real_get_preferred_height (ClutterLayoutManager *manager,
static void static void
layout_manager_real_allocate (ClutterLayoutManager *manager, layout_manager_real_allocate (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation) const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{ {
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "allocate"); LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "allocate");
} }
@@ -297,12 +301,96 @@ layout_manager_real_get_child_meta_type (ClutterLayoutManager *manager)
return G_TYPE_INVALID; return G_TYPE_INVALID;
} }
/* XXX:2.0 - Remove */
static ClutterAlpha *
layout_manager_real_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode)
{
ClutterTimeline *timeline;
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha != NULL)
{
clutter_alpha_set_mode (alpha, mode);
timeline = clutter_alpha_get_timeline (alpha);
clutter_timeline_set_duration (timeline, duration);
clutter_timeline_rewind (timeline);
return alpha;
};
timeline = clutter_timeline_new (duration);
alpha = clutter_alpha_new_full (timeline, mode);
/* let the alpha take ownership of the timeline */
g_object_unref (timeline);
g_signal_connect_swapped (timeline, "new-frame",
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
g_object_set_qdata_full (G_OBJECT (manager),
quark_layout_alpha, alpha,
(GDestroyNotify) g_object_unref);
clutter_timeline_start (timeline);
return alpha;
}
/* XXX:2.0 - Remove */
static gdouble
layout_manager_real_get_animation_progress (ClutterLayoutManager *manager)
{
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha == NULL)
return 1.0;
return clutter_alpha_get_alpha (alpha);
}
/* XXX:2.0 - Remove */
static void
layout_manager_real_end_animation (ClutterLayoutManager *manager)
{
ClutterTimeline *timeline;
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha == NULL)
return;
timeline = clutter_alpha_get_timeline (alpha);
g_assert (timeline != NULL);
if (clutter_timeline_is_playing (timeline))
clutter_timeline_stop (timeline);
g_signal_handlers_disconnect_by_func (timeline,
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
g_object_set_qdata (G_OBJECT (manager), quark_layout_alpha, NULL);
clutter_layout_manager_layout_changed (manager);
}
static void static void
clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass) clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass)
{ {
quark_layout_meta = quark_layout_meta =
g_quark_from_static_string ("clutter-layout-manager-child-meta"); g_quark_from_static_string ("clutter-layout-manager-child-meta");
/* XXX:2.0 - Remove */
quark_layout_alpha =
g_quark_from_static_string ("clutter-layout-manager-alpha");
klass->get_preferred_width = layout_manager_real_get_preferred_width; klass->get_preferred_width = layout_manager_real_get_preferred_width;
klass->get_preferred_height = layout_manager_real_get_preferred_height; klass->get_preferred_height = layout_manager_real_get_preferred_height;
klass->allocate = layout_manager_real_allocate; klass->allocate = layout_manager_real_allocate;
@@ -310,6 +398,9 @@ clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass)
klass->get_child_meta_type = layout_manager_real_get_child_meta_type; klass->get_child_meta_type = layout_manager_real_get_child_meta_type;
/* XXX:2.0 - Remove */ /* XXX:2.0 - Remove */
klass->begin_animation = layout_manager_real_begin_animation;
klass->get_animation_progress = layout_manager_real_get_animation_progress;
klass->end_animation = layout_manager_real_end_animation;
klass->set_container = layout_manager_real_set_container; klass->set_container = layout_manager_real_set_container;
/** /**
@@ -432,6 +523,7 @@ clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager,
* @container: the #ClutterContainer using @manager * @container: the #ClutterContainer using @manager
* @allocation: the #ClutterActorBox containing the allocated area * @allocation: the #ClutterActorBox containing the allocated area
* of @container * of @container
* @flags: the allocation flags
* *
* Allocates the children of @container given an area * Allocates the children of @container given an area
* *
@@ -442,7 +534,8 @@ clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager,
void void
clutter_layout_manager_allocate (ClutterLayoutManager *manager, clutter_layout_manager_allocate (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation) const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{ {
ClutterLayoutManagerClass *klass; ClutterLayoutManagerClass *klass;
@@ -451,7 +544,7 @@ clutter_layout_manager_allocate (ClutterLayoutManager *manager,
g_return_if_fail (allocation != NULL); g_return_if_fail (allocation != NULL);
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager); klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
klass->allocate (manager, container, allocation); klass->allocate (manager, container, allocation, flags);
} }
/** /**

View File

@@ -115,7 +115,8 @@ struct _ClutterLayoutManagerClass
gfloat *nat_height_p); gfloat *nat_height_p);
void (* allocate) (ClutterLayoutManager *manager, void (* allocate) (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation); const ClutterActorBox *allocation,
ClutterAllocationFlags flags);
void (* set_container) (ClutterLayoutManager *manager, void (* set_container) (ClutterLayoutManager *manager,
ClutterContainer *container); ClutterContainer *container);
@@ -125,6 +126,15 @@ struct _ClutterLayoutManagerClass
ClutterContainer *container, ClutterContainer *container,
ClutterActor *actor); ClutterActor *actor);
/* deprecated */
ClutterAlpha * (* begin_animation) (ClutterLayoutManager *manager,
guint duration,
gulong mode);
/* deprecated */
gdouble (* get_animation_progress) (ClutterLayoutManager *manager);
/* deprecated */
void (* end_animation) (ClutterLayoutManager *manager);
void (* layout_changed) (ClutterLayoutManager *manager); void (* layout_changed) (ClutterLayoutManager *manager);
/*< private >*/ /*< private >*/
@@ -157,7 +167,8 @@ void clutter_layout_manager_get_preferred_height (ClutterLayoutMa
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_layout_manager_allocate (ClutterLayoutManager *manager, void clutter_layout_manager_allocate (ClutterLayoutManager *manager,
ClutterContainer *container, ClutterContainer *container,
const ClutterActorBox *allocation); const ClutterActorBox *allocation,
ClutterAllocationFlags flags);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_layout_manager_set_container (ClutterLayoutManager *manager, void clutter_layout_manager_set_container (ClutterLayoutManager *manager,

View File

@@ -61,6 +61,7 @@
#include "clutter-input-pointer-a11y-private.h" #include "clutter-input-pointer-a11y-private.h"
#include "clutter-graphene.h" #include "clutter-graphene.h"
#include "clutter-main.h" #include "clutter-main.h"
#include "clutter-master-clock.h"
#include "clutter-mutter.h" #include "clutter-mutter.h"
#include "clutter-paint-node-private.h" #include "clutter-paint-node-private.h"
#include "clutter-private.h" #include "clutter-private.h"
@@ -82,6 +83,10 @@
/* main context */ /* main context */
static ClutterMainContext *ClutterCntx = NULL; static ClutterMainContext *ClutterCntx = NULL;
G_LOCK_DEFINE_STATIC (ClutterCntx);
/* main lock and locking/unlocking functions */
static GMutex clutter_threads_mutex;
/* command line options */ /* command line options */
static gboolean clutter_is_initialized = FALSE; static gboolean clutter_is_initialized = FALSE;
@@ -140,6 +145,12 @@ static const GDebugKey clutter_paint_debug_keys[] = {
{ "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION }, { "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION },
}; };
static inline void
clutter_threads_init_default (void)
{
g_mutex_init (&clutter_threads_mutex);
}
#define ENVIRONMENT_GROUP "Environment" #define ENVIRONMENT_GROUP "Environment"
#define DEBUG_GROUP "Debug" #define DEBUG_GROUP "Debug"
@@ -508,7 +519,11 @@ clutter_main (void)
main_loops = g_slist_prepend (main_loops, loop); main_loops = g_slist_prepend (main_loops, loop);
if (g_main_loop_is_running (main_loops->data)) if (g_main_loop_is_running (main_loops->data))
g_main_loop_run (loop); {
_clutter_threads_release_lock ();
g_main_loop_run (loop);
_clutter_threads_acquire_lock ();
}
main_loops = g_slist_remove (main_loops, loop); main_loops = g_slist_remove (main_loops, loop);
@@ -525,9 +540,13 @@ _clutter_threads_dispatch (gpointer data)
ClutterThreadsDispatch *dispatch = data; ClutterThreadsDispatch *dispatch = data;
gboolean ret = FALSE; gboolean ret = FALSE;
_clutter_threads_acquire_lock ();
if (!g_source_is_destroyed (g_main_current_source ())) if (!g_source_is_destroyed (g_main_current_source ()))
ret = dispatch->func (dispatch->data); ret = dispatch->func (dispatch->data);
_clutter_threads_release_lock ();
return ret; return ret;
} }
@@ -752,6 +771,40 @@ clutter_threads_add_timeout (guint interval,
NULL); NULL);
} }
void
_clutter_threads_acquire_lock (void)
{
g_mutex_lock (&clutter_threads_mutex);
}
void
_clutter_threads_release_lock (void)
{
/* we need to trylock here, in case the lock hasn't been acquired; on
* various systems trying to release a mutex that hasn't been acquired
* will cause a run-time error. trylock() will either fail, in which
* case we can release the lock we own; or it will succeeds, in which
* case we need to release the lock we just acquired. so we ignore the
* returned value.
*
* see: https://bugs.gnome.org/679439
*/
g_mutex_trylock (&clutter_threads_mutex);
g_mutex_unlock (&clutter_threads_mutex);
}
void
_clutter_context_lock (void)
{
G_LOCK (ClutterCntx);
}
void
_clutter_context_unlock (void)
{
G_UNLOCK (ClutterCntx);
}
gboolean gboolean
_clutter_context_is_initialized (void) _clutter_context_is_initialized (void)
{ {
@@ -761,8 +814,8 @@ _clutter_context_is_initialized (void)
return ClutterCntx->is_initialized; return ClutterCntx->is_initialized;
} }
ClutterMainContext * static ClutterMainContext *
_clutter_context_get_default (void) clutter_context_get_default_unlocked (void)
{ {
if (G_UNLIKELY (ClutterCntx == NULL)) if (G_UNLIKELY (ClutterCntx == NULL))
{ {
@@ -793,6 +846,20 @@ _clutter_context_get_default (void)
return ClutterCntx; return ClutterCntx;
} }
ClutterMainContext *
_clutter_context_get_default (void)
{
ClutterMainContext *retval;
_clutter_context_lock ();
retval = clutter_context_get_default_unlocked ();
_clutter_context_unlock ();
return retval;
}
static gboolean static gboolean
clutter_arg_direction_cb (const char *key, clutter_arg_direction_cb (const char *key,
const char *value, const char *value,
@@ -1982,8 +2049,7 @@ _clutter_process_event_details (ClutterActor *stage,
emit_touch_event (event, device); emit_touch_event (event, device);
if (event->type == CLUTTER_TOUCH_END || if (event->type == CLUTTER_TOUCH_END)
event->type == CLUTTER_TOUCH_CANCEL)
_clutter_input_device_remove_event_sequence (device, event); _clutter_input_device_remove_event_sequence (device, event);
break; break;
@@ -2018,8 +2084,7 @@ _clutter_process_event_details (ClutterActor *stage,
emit_touch_event (event, device); emit_touch_event (event, device);
if (event->type == CLUTTER_TOUCH_END || if (event->type == CLUTTER_TOUCH_END)
event->type == CLUTTER_TOUCH_CANCEL)
_clutter_input_device_remove_event_sequence (device, event); _clutter_input_device_remove_event_sequence (device, event);
break; break;
@@ -2089,6 +2154,27 @@ _clutter_process_event (ClutterEvent *event)
context->current_event = g_slist_delete_link (context->current_event, context->current_event); context->current_event = g_slist_delete_link (context->current_event, context->current_event);
} }
/**
* clutter_get_actor_by_gid:
* @id_: a #ClutterActor unique id.
*
* Retrieves the #ClutterActor with @id_.
*
* Return value: (transfer none): the actor with the passed id or %NULL.
* The returned actor does not have its reference count increased.
*
* Since: 0.6
*
* Deprecated: 1.8: The id is deprecated, and this function always returns
* %NULL. Use the proper scene graph API in #ClutterActor to find a child
* of the stage.
*/
ClutterActor *
clutter_get_actor_by_gid (guint32 id_)
{
return NULL;
}
void void
clutter_base_init (void) clutter_base_init (void)
{ {
@@ -2103,6 +2189,9 @@ clutter_base_init (void)
g_type_init (); g_type_init ();
#endif #endif
/* initialise the Big Clutter Lock™ if necessary */
clutter_threads_init_default ();
clutter_graphene_init (); clutter_graphene_init ();
} }
} }
@@ -2170,7 +2259,9 @@ clutter_threads_remove_repaint_func (guint handle_id)
g_return_if_fail (handle_id > 0); g_return_if_fail (handle_id > 0);
context = _clutter_context_get_default (); _clutter_context_lock ();
context = clutter_context_get_default_unlocked ();
l = context->repaint_funcs; l = context->repaint_funcs;
while (l != NULL) while (l != NULL)
{ {
@@ -2193,6 +2284,8 @@ clutter_threads_remove_repaint_func (guint handle_id)
l = l->next; l = l->next;
} }
_clutter_context_unlock ();
} }
/** /**
@@ -2291,13 +2384,16 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
g_return_val_if_fail (func != NULL, 0); g_return_val_if_fail (func != NULL, 0);
context = _clutter_context_get_default (); _clutter_context_lock ();
context = clutter_context_get_default_unlocked ();
repaint_func = g_slice_new (ClutterRepaintFunction); repaint_func = g_slice_new (ClutterRepaintFunction);
repaint_func->id = context->last_repaint_id++; repaint_func->id = context->last_repaint_id++;
repaint_func->flags = flags; /* mask out QUEUE_REDRAW_ON_ADD, since we're going to consume it */
repaint_func->flags = flags & ~CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD;
repaint_func->func = func; repaint_func->func = func;
repaint_func->data = data; repaint_func->data = data;
repaint_func->notify = notify; repaint_func->notify = notify;
@@ -2305,6 +2401,15 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
context->repaint_funcs = g_list_prepend (context->repaint_funcs, context->repaint_funcs = g_list_prepend (context->repaint_funcs,
repaint_func); repaint_func);
_clutter_context_unlock ();
if ((flags & CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD) != 0)
{
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
_clutter_master_clock_ensure_next_iteration (master_clock);
}
return repaint_func->id; return repaint_func->id;
} }

View File

@@ -0,0 +1,642 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* SECTION:clutter-master-clock-default
* @short_description: The default master clock for all animations
*
* The #ClutterMasterClockDefault class is the default implementation
* of #ClutterMasterClock.
*/
#include "clutter-build-config.h"
#include <cogl/cogl.h>
#include "clutter-master-clock.h"
#include "clutter-master-clock-default.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
#ifdef CLUTTER_ENABLE_DEBUG
#define clutter_warn_if_over_budget(master_clock,start_time,section) G_STMT_START { \
gint64 __delta = g_get_monotonic_time () - start_time; \
gint64 __budget = master_clock->remaining_budget; \
if (__budget > 0 && __delta >= __budget) { \
_clutter_diagnostic_message ("%s took %" G_GINT64_FORMAT " microseconds " \
"more than the remaining budget of %" G_GINT64_FORMAT \
" microseconds", \
section, __delta - __budget, __budget); \
} } G_STMT_END
#else
#define clutter_warn_if_over_budget(master_clock,start_time,section)
#endif
typedef struct _ClutterClockSource ClutterClockSource;
struct _ClutterMasterClockDefault
{
GObject parent_instance;
/* the list of timelines handled by the clock */
GSList *timelines;
/* the current state of the clock, in usecs */
gint64 cur_tick;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 frame_budget;
gint64 remaining_budget;
#endif
/* an idle source, used by the Master Clock to queue
* a redraw on the stage and drive the animations
*/
GSource *source;
guint ensure_next_iteration : 1;
guint paused : 1;
};
struct _ClutterClockSource
{
GSource source;
ClutterMasterClockDefault *master_clock;
};
static gboolean clutter_clock_prepare (GSource *source,
gint *timeout);
static gboolean clutter_clock_check (GSource *source);
static gboolean clutter_clock_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data);
static GSourceFuncs clock_funcs = {
clutter_clock_prepare,
clutter_clock_check,
clutter_clock_dispatch,
NULL
};
static void
clutter_master_clock_iface_init (ClutterMasterClockInterface *iface);
#define clutter_master_clock_default_get_type _clutter_master_clock_default_get_type
G_DEFINE_TYPE_WITH_CODE (ClutterMasterClockDefault,
clutter_master_clock_default,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_MASTER_CLOCK,
clutter_master_clock_iface_init));
/*
* master_clock_is_running:
* @master_clock: a #ClutterMasterClock
*
* Checks if we should currently be advancing timelines or redrawing
* stages.
*
* Return value: %TRUE if the #ClutterMasterClock has at least
* one running timeline
*/
static gboolean
master_clock_is_running (ClutterMasterClockDefault *master_clock)
{
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
const GSList *stages, *l;
stages = clutter_stage_manager_peek_stages (stage_manager);
if (master_clock->paused)
return FALSE;
if (master_clock->timelines)
return TRUE;
for (l = stages; l; l = l->next)
{
if (clutter_actor_is_mapped (l->data) &&
(_clutter_stage_has_queued_events (l->data) ||
_clutter_stage_needs_update (l->data)))
return TRUE;
}
if (master_clock->ensure_next_iteration)
{
master_clock->ensure_next_iteration = FALSE;
return TRUE;
}
return FALSE;
}
static gint
master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock)
{
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
const GSList *stages, *l;
gint64 min_update_time = -1;
stages = clutter_stage_manager_peek_stages (stage_manager);
for (l = stages; l != NULL; l = l->next)
{
gint64 update_time = _clutter_stage_get_update_time (l->data);
if (min_update_time == -1 ||
(update_time != -1 && update_time < min_update_time))
min_update_time = update_time;
}
if (min_update_time == -1)
{
return -1;
}
else
{
gint64 now = g_source_get_time (master_clock->source);
if (min_update_time < now)
{
return 0;
}
else
{
gint64 delay_us = min_update_time - now;
return (delay_us + 999) / 1000;
}
}
}
static int64_t
master_clock_get_next_presentation_time (ClutterMasterClockDefault *master_clock)
{
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
const GSList *stages, *l;
int64_t earliest = -1;
stages = clutter_stage_manager_peek_stages (stage_manager);
for (l = stages; l != NULL; l = l->next)
{
gint64 t = _clutter_stage_get_next_presentation_time (l->data);
if (earliest == -1 || (t != -1 && t < earliest))
earliest = t;
}
return earliest;
}
static void
master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock)
{
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
const GSList *stages, *l;
stages = clutter_stage_manager_peek_stages (stage_manager);
for (l = stages; l != NULL; l = l->next)
_clutter_stage_schedule_update (l->data);
}
static GSList *
master_clock_list_ready_stages (ClutterMasterClockDefault *master_clock)
{
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
const GSList *stages, *l;
GSList *result;
stages = clutter_stage_manager_peek_stages (stage_manager);
result = NULL;
for (l = stages; l != NULL; l = l->next)
{
gint64 update_time = _clutter_stage_get_update_time (l->data);
/* We carefully avoid to update stages that aren't mapped, because
* they have nothing to render and this could cause a deadlock with
* some of the SwapBuffers implementations (in particular
* GLX_INTEL_swap_event is not emitted if nothing was rendered).
*
* Also, if a stage has a swap-buffers pending we don't want to draw
* to it in case the driver may block the CPU while it waits for the
* next backbuffer to become available.
*
* TODO: We should be able to identify if we are running triple or N
* buffered and in these cases we can still draw if there is 1 swap
* pending so we can hopefully always be ready to swap for the next
* vblank and really match the vsync frequency.
*/
if (clutter_actor_is_mapped (l->data) &&
update_time != -1 && update_time <= master_clock->cur_tick)
result = g_slist_prepend (result, g_object_ref (l->data));
}
return g_slist_reverse (result);
}
static void
master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
GSList *stages)
{
const GSList *l;
for (l = stages; l != NULL; l = l->next)
{
/* Clear the old update time */
_clutter_stage_clear_update_time (l->data);
/* And if there is still work to be done, schedule a new one */
if (master_clock->timelines ||
_clutter_stage_has_queued_events (l->data) ||
_clutter_stage_needs_update (l->data))
_clutter_stage_schedule_update (l->data);
}
}
/*
* master_clock_next_frame_delay:
* @master_clock: a #ClutterMasterClock
*
* Computes the number of delay before we need to draw the next frame.
*
* Return value: -1 if there is no next frame pending, otherwise the
* number of millseconds before the we need to draw the next frame
*/
static gint
master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
{
if (!master_clock_is_running (master_clock))
return -1;
/* If all of the stages are busy waiting for a swap-buffers to complete
* then we wait for one to be ready.. */
return master_clock_get_swap_wait_time (master_clock);
}
static void
master_clock_process_events (ClutterMasterClockDefault *master_clock,
GSList *stages)
{
GSList *l;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 start = g_get_monotonic_time ();
#endif
/* Process queued events */
for (l = stages; l != NULL; l = l->next)
_clutter_stage_process_queued_events (l->data);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Event processing");
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
#endif
}
/*
* master_clock_advance_timelines:
* @master_clock: a #ClutterMasterClock
*
* Advances all the timelines held by the master clock. This function
* should be called before calling _clutter_stage_do_update() to
* make sure that all the timelines are advanced and the scene is updated.
*/
static void
master_clock_advance_timelines (ClutterMasterClockDefault *master_clock)
{
GSList *timelines, *l;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 start = g_get_monotonic_time ();
#endif
/* we protect ourselves from timelines being removed during
* the advancement by other timelines by copying the list of
* timelines, taking a reference on them, iterating over the
* copied list and then releasing the reference.
*
* we cannot simply take a reference on the timelines and still
* use the list held by the master clock because the do_tick()
* might result in the creation of a new timeline, which gets
* added at the end of the list with no reference increase and
* thus gets disposed at the end of the iteration.
*
* this implies that a newly added timeline will not be advanced
* by this clock iteration, which is perfectly fine since we're
* in its first cycle.
*
* we also cannot steal the master clock timelines list because
* a timeline might be removed as the direct result of do_tick()
* and remove_timeline() would not find the timeline, failing
* and leaving a dangling pointer behind.
*/
timelines = g_slist_copy (master_clock->timelines);
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
for (l = timelines; l != NULL; l = l->next)
_clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000);
g_slist_free_full (timelines, g_object_unref);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Animations");
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
#endif
}
static gboolean
master_clock_update_stages (ClutterMasterClockDefault *master_clock,
GSList *stages)
{
gboolean stages_updated = FALSE;
GSList *l;
#ifdef CLUTTER_ENABLE_DEBUG
gint64 start = g_get_monotonic_time ();
#endif
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT);
/* Update any stage that needs redraw/relayout after the clock
* is advanced.
*/
for (l = stages; l != NULL; l = l->next)
stages_updated |= _clutter_stage_do_update (l->data);
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
#ifdef CLUTTER_ENABLE_DEBUG
if (_clutter_diagnostic_enabled ())
clutter_warn_if_over_budget (master_clock, start, "Updating the stage");
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
#endif
return stages_updated;
}
/*
* clutter_clock_source_new:
* @master_clock: a #ClutterMasterClock for the source
*
* The #ClutterClockSource is an idle GSource that will queue a redraw
* if @master_clock has at least a running #ClutterTimeline. The redraw
* will cause @master_clock to advance all timelines, thus advancing all
* animations as well.
*
* Return value: the newly created #GSource
*/
static GSource *
clutter_clock_source_new (ClutterMasterClockDefault *master_clock)
{
GSource *source = g_source_new (&clock_funcs, sizeof (ClutterClockSource));
ClutterClockSource *clock_source = (ClutterClockSource *) source;
g_source_set_name (source, "Clutter master clock");
g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
g_source_set_can_recurse (source, FALSE);
clock_source->master_clock = master_clock;
return source;
}
static gboolean
clutter_clock_prepare (GSource *source,
gint *timeout)
{
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
int delay;
_clutter_threads_acquire_lock ();
if (G_UNLIKELY (clutter_paint_debug_flags &
CLUTTER_DEBUG_CONTINUOUS_REDRAW))
{
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
const GSList *stages, *l;
stages = clutter_stage_manager_peek_stages (stage_manager);
/* Queue a full redraw on all of the stages */
for (l = stages; l != NULL; l = l->next)
clutter_actor_queue_redraw (l->data);
}
delay = master_clock_next_frame_delay (master_clock);
_clutter_threads_release_lock ();
*timeout = delay;
return delay == 0;
}
static gboolean
clutter_clock_check (GSource *source)
{
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
int delay;
_clutter_threads_acquire_lock ();
delay = master_clock_next_frame_delay (master_clock);
_clutter_threads_release_lock ();
return delay == 0;
}
static gboolean
clutter_clock_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterClockSource *clock_source = (ClutterClockSource *) source;
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
GSList *stages;
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
_clutter_threads_acquire_lock ();
COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)");
/* Get the time to use for this frame */
master_clock->cur_tick = master_clock_get_next_presentation_time (master_clock);
/* On the first frame the backend might not have an answer */
if (master_clock->cur_tick <= 0)
master_clock->cur_tick = g_source_get_time (source);
#ifdef CLUTTER_ENABLE_DEBUG
master_clock->remaining_budget = master_clock->frame_budget;
#endif
/* We need to protect ourselves against stages being destroyed during
* event handling - master_clock_list_ready_stages() returns a
* list of referenced that we'll unref afterwards.
*/
stages = master_clock_list_ready_stages (master_clock);
/* Each frame is split into three separate phases: */
/* 1. process all the events; each stage goes through its events queue
* and processes each event according to its type, then emits the
* various signals that are associated with the event
*/
master_clock_process_events (master_clock, stages);
/* 2. advance the timelines */
master_clock_advance_timelines (master_clock);
/* 3. relayout and redraw the stages */
master_clock_update_stages (master_clock, stages);
master_clock_reschedule_stage_updates (master_clock, stages);
g_slist_free_full (stages, g_object_unref);
COGL_TRACE_END (ClutterMasterClockTick);
_clutter_threads_release_lock ();
return TRUE;
}
static void
clutter_master_clock_default_finalize (GObject *gobject)
{
ClutterMasterClockDefault *master_clock = CLUTTER_MASTER_CLOCK_DEFAULT (gobject);
g_slist_free (master_clock->timelines);
G_OBJECT_CLASS (clutter_master_clock_default_parent_class)->finalize (gobject);
}
static void
clutter_master_clock_default_class_init (ClutterMasterClockDefaultClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = clutter_master_clock_default_finalize;
}
static void
clutter_master_clock_default_init (ClutterMasterClockDefault *self)
{
GSource *source;
source = clutter_clock_source_new (self);
self->source = source;
self->ensure_next_iteration = FALSE;
self->paused = FALSE;
#ifdef CLUTTER_ENABLE_DEBUG
self->frame_budget = G_USEC_PER_SEC / 60;
#endif
g_source_attach (source, NULL);
}
static void
clutter_master_clock_default_add_timeline (ClutterMasterClock *clock,
ClutterTimeline *timeline)
{
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
gboolean is_first;
if (g_slist_find (master_clock->timelines, timeline))
return;
is_first = master_clock->timelines == NULL;
master_clock->timelines = g_slist_prepend (master_clock->timelines,
timeline);
if (is_first)
{
master_clock_schedule_stage_updates (master_clock);
_clutter_master_clock_start_running (clock);
}
}
static void
clutter_master_clock_default_remove_timeline (ClutterMasterClock *clock,
ClutterTimeline *timeline)
{
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
master_clock->timelines = g_slist_remove (master_clock->timelines,
timeline);
}
static void
clutter_master_clock_default_start_running (ClutterMasterClock *master_clock)
{
/* If called from a different thread, we need to wake up the
* main loop to start running the timelines
*/
g_main_context_wakeup (NULL);
}
static void
clutter_master_clock_default_ensure_next_iteration (ClutterMasterClock *clock)
{
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
master_clock->ensure_next_iteration = TRUE;
}
static void
clutter_master_clock_default_set_paused (ClutterMasterClock *clock,
gboolean paused)
{
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
if (paused && !master_clock->paused)
{
g_clear_pointer (&master_clock->source, g_source_destroy);
}
else if (!paused && master_clock->paused)
{
master_clock->source = clutter_clock_source_new (master_clock);
g_source_attach (master_clock->source, NULL);
}
master_clock->paused = !!paused;
}
static void
clutter_master_clock_iface_init (ClutterMasterClockInterface *iface)
{
iface->add_timeline = clutter_master_clock_default_add_timeline;
iface->remove_timeline = clutter_master_clock_default_remove_timeline;
iface->start_running = clutter_master_clock_default_start_running;
iface->ensure_next_iteration = clutter_master_clock_default_ensure_next_iteration;
iface->set_paused = clutter_master_clock_default_set_paused;
}

View File

@@ -0,0 +1,48 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com>
*
* Copyright (C) 2015 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/>.
*/
#ifndef __CLUTTER_MASTER_CLOCK_DEFAULT_H__
#define __CLUTTER_MASTER_CLOCK_DEFAULT_H__
#include <clutter/clutter-timeline.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_MASTER_CLOCK_DEFAULT (_clutter_master_clock_default_get_type ())
#define CLUTTER_MASTER_CLOCK_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefault))
#define CLUTTER_IS_MASTER_CLOCK_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT))
#define CLUTTER_MASTER_CLOCK_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefaultClass))
typedef struct _ClutterMasterClockDefault ClutterMasterClockDefault;
typedef struct _ClutterMasterClockDefaultClass ClutterMasterClockDefaultClass;
struct _ClutterMasterClockDefaultClass
{
GObjectClass parent_class;
};
GType _clutter_master_clock_default_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __CLUTTER_MASTER_CLOCK_DEFAULT_H__ */

View File

@@ -0,0 +1,132 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* SECTION:clutter-master-clock
* @short_description: The master clock for all animations
*
* The #ClutterMasterClock class is responsible for advancing all
* #ClutterTimelines when a stage is being redrawn. The master clock
* makes sure that the scenegraph is always integrally updated before
* painting it.
*/
#include "clutter-build-config.h"
#include "clutter-master-clock.h"
#include "clutter-master-clock-default.h"
#include "clutter-private.h"
G_DEFINE_INTERFACE (ClutterMasterClock, clutter_master_clock, G_TYPE_OBJECT)
static void
clutter_master_clock_default_init (ClutterMasterClockInterface *iface)
{
}
ClutterMasterClock *
_clutter_master_clock_get_default (void)
{
ClutterMainContext *context = _clutter_context_get_default ();
if (G_UNLIKELY (context->master_clock == NULL))
context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, NULL);
return context->master_clock;
}
/*
* _clutter_master_clock_add_timeline:
* @master_clock: a #ClutterMasterClock
* @timeline: a #ClutterTimeline
*
* Adds @timeline to the list of playing timelines held by the master
* clock.
*/
void
_clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
ClutterTimeline *timeline)
{
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->add_timeline (master_clock,
timeline);
}
/*
* _clutter_master_clock_remove_timeline:
* @master_clock: a #ClutterMasterClock
* @timeline: a #ClutterTimeline
*
* Removes @timeline from the list of playing timelines held by the
* master clock.
*/
void
_clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock,
ClutterTimeline *timeline)
{
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->remove_timeline (master_clock,
timeline);
}
/*
* _clutter_master_clock_start_running:
* @master_clock: a #ClutterMasterClock
*
* Called when we have events or redraws to process; if the clock
* is stopped, does the processing necessary to wake it up again.
*/
void
_clutter_master_clock_start_running (ClutterMasterClock *master_clock)
{
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->start_running (master_clock);
}
/**
* _clutter_master_clock_ensure_next_iteration:
* @master_clock: a #ClutterMasterClock
*
* Ensures that the master clock will run at least one iteration
*/
void
_clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock)
{
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->ensure_next_iteration (master_clock);
}
void
_clutter_master_clock_set_paused (ClutterMasterClock *master_clock,
gboolean paused)
{
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->set_paused (master_clock,
!!paused);
}

View File

@@ -0,0 +1,69 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CLUTTER_MASTER_CLOCK_H__
#define __CLUTTER_MASTER_CLOCK_H__
#include <clutter/clutter-timeline.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_MASTER_CLOCK (clutter_master_clock_get_type ())
G_DECLARE_INTERFACE (ClutterMasterClock, clutter_master_clock,
CLUTTER, MASTER_CLOCK,
GObject)
struct _ClutterMasterClockInterface
{
/*< private >*/
GTypeInterface parent_iface;
void (* add_timeline) (ClutterMasterClock *master_clock,
ClutterTimeline *timeline);
void (* remove_timeline) (ClutterMasterClock *master_clock,
ClutterTimeline *timeline);
void (* start_running) (ClutterMasterClock *master_clock);
void (* ensure_next_iteration) (ClutterMasterClock *master_clock);
void (* set_paused) (ClutterMasterClock *master_clock,
gboolean paused);
};
ClutterMasterClock * _clutter_master_clock_get_default (void);
void _clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
ClutterTimeline *timeline);
void _clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock,
ClutterTimeline *timeline);
void _clutter_master_clock_start_running (ClutterMasterClock *master_clock);
void _clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock);
void _clutter_master_clock_set_paused (ClutterMasterClock *master_clock,
gboolean paused);
void _clutter_timeline_advance (ClutterTimeline *timeline,
gint64 tick_time);
gint64 _clutter_timeline_get_delta (ClutterTimeline *timeline);
void _clutter_timeline_do_tick (ClutterTimeline *timeline,
gint64 tick_time);
G_END_DECLS
#endif /* __CLUTTER_MASTER_CLOCK_H__ */

View File

@@ -36,13 +36,6 @@
#include "cogl/clutter-stage-cogl.h" #include "cogl/clutter-stage-cogl.h"
#include "clutter/x11/clutter-backend-x11.h" #include "clutter/x11/clutter-backend-x11.h"
CLUTTER_EXPORT
GList * clutter_stage_peek_stage_views (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_actor_is_effectively_on_stage_view (ClutterActor *self,
ClutterStageView *view);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_set_custom_backend_func (ClutterBackend *(* func) (void)); void clutter_set_custom_backend_func (ClutterBackend *(* func) (void));
@@ -56,35 +49,17 @@ void clutter_stage_capture_into (ClutterStage *stage,
uint8_t *data); uint8_t *data);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_paint_to_framebuffer (ClutterStage *stage, void clutter_stage_freeze_updates (ClutterStage *stage);
CoglFramebuffer *framebuffer,
const cairo_rectangle_int_t *rect,
float scale,
ClutterPaintFlag paint_flags);
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_stage_paint_to_buffer (ClutterStage *stage, void clutter_stage_thaw_updates (ClutterStage *stage);
const cairo_rectangle_int_t *rect,
float scale,
uint8_t *data,
int stride,
CoglPixelFormat format,
ClutterPaintFlag paint_flags,
GError **error);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_clear_stage_views (ClutterStage *stage); void clutter_stage_update_resource_scales (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_view_assign_next_scanout (ClutterStageView *stage_view,
CoglScanout *scanout);
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_actor_has_damage (ClutterActor *actor); gboolean clutter_actor_has_damage (ClutterActor *actor);
CLUTTER_EXPORT
gboolean clutter_actor_has_transitions (ClutterActor *actor);
#undef __CLUTTER_H_INSIDE__ #undef __CLUTTER_H_INSIDE__
#endif /* __CLUTTER_MUTTER_H__ */ #endif /* __CLUTTER_MUTTER_H__ */

View File

@@ -81,7 +81,7 @@
struct _ClutterOffscreenEffectPrivate struct _ClutterOffscreenEffectPrivate
{ {
CoglHandle offscreen; CoglHandle offscreen;
CoglPipeline *pipeline; CoglPipeline *target;
CoglHandle texture; CoglHandle texture;
ClutterActor *actor; ClutterActor *actor;
@@ -140,7 +140,7 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self,
{ {
CoglPipelineFilter filter; CoglPipelineFilter filter;
if (!self->priv->pipeline) if (!self->priv->target)
return; return;
/* If no fractional scaling is set, we're always going to render the texture /* If no fractional scaling is set, we're always going to render the texture
@@ -154,7 +154,7 @@ ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self,
else else
filter = COGL_PIPELINE_FILTER_LINEAR; filter = COGL_PIPELINE_FILTER_LINEAR;
cogl_pipeline_set_layer_filters (self->priv->pipeline, 0 /* layer_index */, cogl_pipeline_set_layer_filters (self->priv->target, 0 /* layer_index */,
filter, filter); filter, filter);
} }
@@ -185,12 +185,12 @@ update_fbo (ClutterEffect *effect,
return TRUE; return TRUE;
} }
if (priv->pipeline == NULL) if (priv->target == NULL)
{ {
CoglContext *ctx = CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ()); clutter_backend_get_cogl_context (clutter_get_default_backend ());
priv->pipeline = cogl_pipeline_new (ctx); priv->target = cogl_pipeline_new (ctx);
ensure_pipeline_filter_for_scale (self, resource_scale); ensure_pipeline_filter_for_scale (self, resource_scale);
} }
@@ -202,7 +202,7 @@ update_fbo (ClutterEffect *effect,
if (priv->texture == NULL) if (priv->texture == NULL)
return FALSE; return FALSE;
cogl_pipeline_set_layer_texture (priv->pipeline, 0, priv->texture); cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture);
priv->target_width = target_width; priv->target_width = target_width;
priv->target_height = target_height; priv->target_height = target_height;
@@ -212,8 +212,8 @@ update_fbo (ClutterEffect *effect,
{ {
g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC); g_warning ("%s: Unable to create an Offscreen buffer", G_STRLOC);
cogl_object_unref (priv->pipeline); cogl_object_unref (priv->target);
priv->pipeline = NULL; priv->target = NULL;
priv->target_width = 0; priv->target_width = 0;
priv->target_height = 0; priv->target_height = 0;
@@ -238,8 +238,8 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
gfloat stage_width, stage_height; gfloat stage_width, stage_height;
gfloat target_width = -1, target_height = -1; gfloat target_width = -1, target_height = -1;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
float resource_scale; gfloat resource_scale;
float ceiled_resource_scale; gfloat ceiled_resource_scale;
graphene_point3d_t local_offset; graphene_point3d_t local_offset;
gfloat old_viewport[4]; gfloat old_viewport[4];
@@ -254,11 +254,17 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
stage = _clutter_actor_get_stage_internal (priv->actor); stage = _clutter_actor_get_stage_internal (priv->actor);
clutter_actor_get_size (stage, &stage_width, &stage_height); clutter_actor_get_size (stage, &stage_width, &stage_height);
resource_scale = clutter_actor_get_real_resource_scale (priv->actor); if (_clutter_actor_get_real_resource_scale (priv->actor, &resource_scale))
{
ceiled_resource_scale = ceilf (resource_scale); ceiled_resource_scale = ceilf (resource_scale);
stage_width *= ceiled_resource_scale; stage_width *= ceiled_resource_scale;
stage_height *= ceiled_resource_scale; stage_height *= ceiled_resource_scale;
}
else
{
/* We are sure we have a resource scale set to a good value at paint */
g_assert_not_reached ();
}
/* Get the minimal bounding box for what we want to paint, relative to the /* Get the minimal bounding box for what we want to paint, relative to the
* parent of priv->actor. Note that we may actually be painting a clone of * parent of priv->actor. Note that we may actually be painting a clone of
@@ -374,7 +380,7 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
paint_opacity = clutter_actor_get_paint_opacity (priv->actor); paint_opacity = clutter_actor_get_paint_opacity (priv->actor);
cogl_pipeline_set_color4ub (priv->pipeline, cogl_pipeline_set_color4ub (priv->target,
paint_opacity, paint_opacity,
paint_opacity, paint_opacity,
paint_opacity, paint_opacity,
@@ -386,7 +392,7 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect,
* hadn't been redirected offscreen. * hadn't been redirected offscreen.
*/ */
cogl_framebuffer_draw_textured_rectangle (framebuffer, cogl_framebuffer_draw_textured_rectangle (framebuffer,
priv->pipeline, priv->target,
0, 0, 0, 0,
cogl_texture_get_width (priv->texture), cogl_texture_get_width (priv->texture),
cogl_texture_get_height (priv->texture), cogl_texture_get_height (priv->texture),
@@ -411,9 +417,8 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
*/ */
cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview); cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
resource_scale = clutter_actor_get_resource_scale (priv->actor); if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) &&
resource_scale != 1.0f)
if (resource_scale != 1.0f)
{ {
float paint_scale = 1.0f / resource_scale; float paint_scale = 1.0f / resource_scale;
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1); cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
@@ -441,16 +446,13 @@ clutter_offscreen_effect_post_paint (ClutterEffect *effect,
ClutterOffscreenEffectPrivate *priv = self->priv; ClutterOffscreenEffectPrivate *priv = self->priv;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
g_warn_if_fail (priv->offscreen); if (priv->offscreen == NULL ||
g_warn_if_fail (priv->pipeline); priv->target == NULL ||
g_warn_if_fail (priv->actor); priv->actor == NULL)
return;
/* Restore the previous opacity override */ /* Restore the previous opacity override */
if (priv->actor) clutter_actor_set_opacity_override (priv->actor, priv->old_opacity_override);
{
clutter_actor_set_opacity_override (priv->actor,
priv->old_opacity_override);
}
framebuffer = clutter_paint_context_get_framebuffer (paint_context); framebuffer = clutter_paint_context_get_framebuffer (paint_context);
cogl_framebuffer_pop_matrix (framebuffer); cogl_framebuffer_pop_matrix (framebuffer);
@@ -496,17 +498,16 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
} }
static void static void
clutter_offscreen_effect_set_enabled (ClutterActorMeta *meta, clutter_offscreen_effect_notify (GObject *gobject,
gboolean is_enabled) GParamSpec *pspec)
{ {
ClutterActorMetaClass *parent_class = ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (gobject);
CLUTTER_ACTOR_META_CLASS (clutter_offscreen_effect_parent_class);
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (meta);
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv; ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
g_clear_pointer (&priv->offscreen, cogl_object_unref); if (strcmp (pspec->name, "enabled") == 0)
g_clear_pointer (&priv->offscreen, cogl_object_unref);
parent_class->set_enabled (meta, is_enabled); G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->notify (gobject, pspec);
} }
static void static void
@@ -517,7 +518,7 @@ clutter_offscreen_effect_finalize (GObject *gobject)
g_clear_pointer (&priv->offscreen, cogl_object_unref); g_clear_pointer (&priv->offscreen, cogl_object_unref);
g_clear_pointer (&priv->texture, cogl_object_unref); g_clear_pointer (&priv->texture, cogl_object_unref);
g_clear_pointer (&priv->pipeline, cogl_object_unref); g_clear_pointer (&priv->target, cogl_object_unref);
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject); G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject);
} }
@@ -533,13 +534,13 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
klass->paint_target = clutter_offscreen_effect_real_paint_target; klass->paint_target = clutter_offscreen_effect_real_paint_target;
meta_class->set_actor = clutter_offscreen_effect_set_actor; meta_class->set_actor = clutter_offscreen_effect_set_actor;
meta_class->set_enabled = clutter_offscreen_effect_set_enabled;
effect_class->pre_paint = clutter_offscreen_effect_pre_paint; effect_class->pre_paint = clutter_offscreen_effect_pre_paint;
effect_class->post_paint = clutter_offscreen_effect_post_paint; effect_class->post_paint = clutter_offscreen_effect_post_paint;
effect_class->paint = clutter_offscreen_effect_paint; effect_class->paint = clutter_offscreen_effect_paint;
gobject_class->finalize = clutter_offscreen_effect_finalize; gobject_class->finalize = clutter_offscreen_effect_finalize;
gobject_class->notify = clutter_offscreen_effect_notify;
} }
static void static void
@@ -599,7 +600,7 @@ clutter_offscreen_effect_get_target (ClutterOffscreenEffect *effect)
g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect), g_return_val_if_fail (CLUTTER_IS_OFFSCREEN_EFFECT (effect),
NULL); NULL);
return (CoglMaterial *)effect->priv->pipeline; return (CoglMaterial *)effect->priv->target;
} }
/** /**

View File

@@ -21,8 +21,7 @@
#include "clutter-paint-context.h" #include "clutter-paint-context.h"
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view, ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip, const cairo_region_t *redraw_clip);
ClutterPaintFlag paint_flags);
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context); gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);

View File

@@ -23,8 +23,6 @@ struct _ClutterPaintContext
{ {
grefcount ref_count; grefcount ref_count;
ClutterPaintFlag paint_flags;
GList *framebuffers; GList *framebuffers;
ClutterStageView *view; ClutterStageView *view;
@@ -38,8 +36,7 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
ClutterPaintContext * ClutterPaintContext *
clutter_paint_context_new_for_view (ClutterStageView *view, clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip, const cairo_region_t *redraw_clip)
ClutterPaintFlag paint_flags)
{ {
ClutterPaintContext *paint_context; ClutterPaintContext *paint_context;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
@@ -48,7 +45,6 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
g_ref_count_init (&paint_context->ref_count); g_ref_count_init (&paint_context->ref_count);
paint_context->view = view; paint_context->view = view;
paint_context->redraw_clip = cairo_region_copy (redraw_clip); paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->paint_flags = paint_flags;
framebuffer = clutter_stage_view_get_framebuffer (view); framebuffer = clutter_stage_view_get_framebuffer (view);
clutter_paint_context_push_framebuffer (paint_context, framebuffer); clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -60,16 +56,12 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
* clutter_paint_context_new_for_framebuffer: (skip) * clutter_paint_context_new_for_framebuffer: (skip)
*/ */
ClutterPaintContext * ClutterPaintContext *
clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer, clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer)
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags)
{ {
ClutterPaintContext *paint_context; ClutterPaintContext *paint_context;
paint_context = g_new0 (ClutterPaintContext, 1); paint_context = g_new0 (ClutterPaintContext, 1);
g_ref_count_init (&paint_context->ref_count); g_ref_count_init (&paint_context->ref_count);
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->paint_flags = paint_flags;
clutter_paint_context_push_framebuffer (paint_context, framebuffer); clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -178,12 +170,3 @@ clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context)
return !paint_context->view; return !paint_context->view;
} }
/**
* clutter_paint_context_get_paint_flags: (skip)
*/
ClutterPaintFlag
clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context)
{
return paint_context->paint_flags;
}

View File

@@ -29,21 +29,13 @@
typedef struct _ClutterPaintContext ClutterPaintContext; typedef struct _ClutterPaintContext ClutterPaintContext;
typedef enum _ClutterPaintFlag
{
CLUTTER_PAINT_FLAG_NONE = 0,
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
} ClutterPaintFlag;
#define CLUTTER_TYPE_PAINT_CONTEXT (clutter_paint_context_get_type ()) #define CLUTTER_TYPE_PAINT_CONTEXT (clutter_paint_context_get_type ())
CLUTTER_EXPORT CLUTTER_EXPORT
GType clutter_paint_context_get_type (void); GType clutter_paint_context_get_type (void);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer, ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer);
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterPaintContext * clutter_paint_context_ref (ClutterPaintContext *paint_context); ClutterPaintContext * clutter_paint_context_ref (ClutterPaintContext *paint_context);
@@ -70,7 +62,4 @@ void clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context);
CLUTTER_EXPORT CLUTTER_EXPORT
const cairo_region_t * clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context); const cairo_region_t * clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context);
CLUTTER_EXPORT
ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context);
#endif /* CLUTTER_PAINT_CONTEXT_H */ #endif /* CLUTTER_PAINT_CONTEXT_H */

View File

@@ -83,6 +83,7 @@ typedef enum
PAINT_OP_INVALID = 0, PAINT_OP_INVALID = 0,
PAINT_OP_TEX_RECT, PAINT_OP_TEX_RECT,
PAINT_OP_MULTITEX_RECT, PAINT_OP_MULTITEX_RECT,
PAINT_OP_PATH,
PAINT_OP_PRIMITIVE PAINT_OP_PRIMITIVE
} PaintOpCode; } PaintOpCode;
@@ -95,6 +96,8 @@ struct _ClutterPaintOperation
union { union {
float texrect[8]; float texrect[8];
CoglPath *path;
CoglPrimitive *primitive; CoglPrimitive *primitive;
} op; } op;
}; };

View File

@@ -782,6 +782,11 @@ clutter_paint_operation_clear (ClutterPaintOperation *op)
g_array_unref (op->multitex_coords); g_array_unref (op->multitex_coords);
break; break;
case PAINT_OP_PATH:
if (op->op.path != NULL)
cogl_object_unref (op->op.path);
break;
case PAINT_OP_PRIMITIVE: case PAINT_OP_PRIMITIVE:
if (op->op.primitive != NULL) if (op->op.primitive != NULL)
cogl_object_unref (op->op.primitive); cogl_object_unref (op->op.primitive);
@@ -831,6 +836,16 @@ clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
op->op.texrect[3] = rect->y2; op->op.texrect[3] = rect->y2;
} }
static inline void
clutter_paint_op_init_path (ClutterPaintOperation *op,
CoglPath *path)
{
clutter_paint_operation_clear (op);
op->opcode = PAINT_OP_PATH;
op->op.path = cogl_object_ref (path);
}
static inline void static inline void
clutter_paint_op_init_primitive (ClutterPaintOperation *op, clutter_paint_op_init_primitive (ClutterPaintOperation *op,
CoglPrimitive *primitive) CoglPrimitive *primitive)
@@ -935,6 +950,34 @@ clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node,
g_array_append_val (node->operations, operation); g_array_append_val (node->operations, operation);
} }
/**
* clutter_paint_node_add_path: (skip)
* @node: a #ClutterPaintNode
* @path: a Cogl path
*
* Adds a region described as a path to the @node.
*
* This function acquires a reference on the passed @path, so it
* is safe to call cogl_object_unref() when it returns.
*
* Since: 1.10
* Stability: unstable
*/
void
clutter_paint_node_add_path (ClutterPaintNode *node,
CoglPath *path)
{
ClutterPaintOperation operation = PAINT_OP_INIT;
g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
g_return_if_fail (cogl_is_path (path));
clutter_paint_node_maybe_init_operations (node);
clutter_paint_op_init_path (&operation, path);
g_array_append_val (node->operations, operation);
}
/** /**
* clutter_paint_node_add_primitive: (skip) * clutter_paint_node_add_primitive: (skip)
* @node: a #ClutterPaintNode * @node: a #ClutterPaintNode
@@ -1071,6 +1114,11 @@ clutter_paint_node_to_json (ClutterPaintNode *node)
json_builder_end_array (builder); json_builder_end_array (builder);
break; break;
case PAINT_OP_PATH:
json_builder_set_member_name (builder, "path");
json_builder_add_int_value (builder, (intptr_t) op->op.path);
break;
case PAINT_OP_PRIMITIVE: case PAINT_OP_PRIMITIVE:
json_builder_set_member_name (builder, "primitive"); json_builder_set_member_name (builder, "primitive");
json_builder_add_int_value (builder, (intptr_t) op->op.primitive); json_builder_add_int_value (builder, (intptr_t) op->op.primitive);

View File

@@ -84,6 +84,9 @@ void clutter_paint_node_add_multitexture_rectangle (ClutterP
unsigned int text_coords_len); unsigned int text_coords_len);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_paint_node_add_path (ClutterPaintNode *node,
CoglPath *path);
CLUTTER_EXPORT
void clutter_paint_node_add_primitive (ClutterPaintNode *node, void clutter_paint_node_add_primitive (ClutterPaintNode *node,
CoglPrimitive *primitive); CoglPrimitive *primitive);

View File

@@ -477,6 +477,10 @@ clutter_pipeline_node_draw (ClutterPaintNode *node,
op->multitex_coords->len); op->multitex_coords->len);
break; break;
case PAINT_OP_PATH:
cogl_framebuffer_fill_path (fb, pnode->pipeline, op->op.path);
break;
case PAINT_OP_PRIMITIVE: case PAINT_OP_PRIMITIVE:
cogl_framebuffer_draw_primitive (fb, cogl_framebuffer_draw_primitive (fb,
pnode->pipeline, pnode->pipeline,
@@ -872,6 +876,7 @@ clutter_text_node_draw (ClutterPaintNode *node,
break; break;
case PAINT_OP_MULTITEX_RECT: case PAINT_OP_MULTITEX_RECT:
case PAINT_OP_PATH:
case PAINT_OP_PRIMITIVE: case PAINT_OP_PRIMITIVE:
case PAINT_OP_INVALID: case PAINT_OP_INVALID:
break; break;
@@ -1032,6 +1037,11 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node,
retval = TRUE; retval = TRUE;
break; break;
case PAINT_OP_PATH:
cogl_framebuffer_push_path_clip (fb, op->op.path);
retval = TRUE;
break;
case PAINT_OP_MULTITEX_RECT: case PAINT_OP_MULTITEX_RECT:
case PAINT_OP_PRIMITIVE: case PAINT_OP_PRIMITIVE:
case PAINT_OP_INVALID: case PAINT_OP_INVALID:
@@ -1062,6 +1072,7 @@ clutter_clip_node_post_draw (ClutterPaintNode *node,
switch (op->opcode) switch (op->opcode)
{ {
case PAINT_OP_PATH:
case PAINT_OP_TEX_RECT: case PAINT_OP_TEX_RECT:
cogl_framebuffer_pop_clip (fb); cogl_framebuffer_pop_clip (fb);
break; break;
@@ -1231,8 +1242,9 @@ struct _ClutterLayerNode
float fbo_width; float fbo_width;
float fbo_height; float fbo_height;
CoglPipeline *pipeline; CoglPipeline *state;
CoglFramebuffer *offscreen; CoglFramebuffer *offscreen;
CoglTexture *texture;
guint8 opacity; guint8 opacity;
}; };
@@ -1322,7 +1334,7 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
case PAINT_OP_TEX_RECT: case PAINT_OP_TEX_RECT:
/* now we need to paint the texture */ /* now we need to paint the texture */
cogl_framebuffer_draw_textured_rectangle (fb, cogl_framebuffer_draw_textured_rectangle (fb,
lnode->pipeline, lnode->state,
op->op.texrect[0], op->op.texrect[0],
op->op.texrect[1], op->op.texrect[1],
op->op.texrect[2], op->op.texrect[2],
@@ -1335,7 +1347,7 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
case PAINT_OP_MULTITEX_RECT: case PAINT_OP_MULTITEX_RECT:
cogl_framebuffer_draw_multitextured_rectangle (fb, cogl_framebuffer_draw_multitextured_rectangle (fb,
lnode->pipeline, lnode->state,
op->op.texrect[0], op->op.texrect[0],
op->op.texrect[1], op->op.texrect[1],
op->op.texrect[2], op->op.texrect[2],
@@ -1344,10 +1356,12 @@ clutter_layer_node_post_draw (ClutterPaintNode *node,
op->multitex_coords->len); op->multitex_coords->len);
break; break;
case PAINT_OP_PATH:
cogl_framebuffer_fill_path (fb, lnode->state, op->op.path);
break;
case PAINT_OP_PRIMITIVE: case PAINT_OP_PRIMITIVE:
cogl_framebuffer_draw_primitive (fb, cogl_framebuffer_draw_primitive (fb, lnode->state, op->op.primitive);
lnode->pipeline,
op->op.primitive);
break; break;
} }
} }
@@ -1358,8 +1372,8 @@ clutter_layer_node_finalize (ClutterPaintNode *node)
{ {
ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node); ClutterLayerNode *lnode = CLUTTER_LAYER_NODE (node);
if (lnode->pipeline != NULL) if (lnode->state != NULL)
cogl_object_unref (lnode->pipeline); cogl_object_unref (lnode->state);
if (lnode->offscreen != NULL) if (lnode->offscreen != NULL)
cogl_object_unref (lnode->offscreen); cogl_object_unref (lnode->offscreen);
@@ -1411,9 +1425,6 @@ clutter_layer_node_new (const CoglMatrix *projection,
guint8 opacity) guint8 opacity)
{ {
ClutterLayerNode *res; ClutterLayerNode *res;
CoglContext *context;
CoglTexture2D *tex_2d;
CoglTexture *texture;
CoglColor color; CoglColor color;
res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE); res = _clutter_paint_node_create (CLUTTER_TYPE_LAYER_NODE);
@@ -1425,18 +1436,19 @@ clutter_layer_node_new (const CoglMatrix *projection,
res->opacity = opacity; res->opacity = opacity;
/* the texture backing the FBO */ /* the texture backing the FBO */
context = clutter_backend_get_cogl_context (clutter_get_default_backend ()); res->texture = cogl_texture_new_with_size (MAX (res->fbo_width, 1),
MAX (res->fbo_height, 1),
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_RGBA_8888_PRE);
tex_2d = cogl_texture_2d_new_with_size (context, res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (res->texture));
MAX (res->fbo_width, 1),
MAX (res->fbo_height, 1));
texture = COGL_TEXTURE (tex_2d);
cogl_texture_set_premultiplied (texture, TRUE);
res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture));
if (res->offscreen == NULL) if (res->offscreen == NULL)
{ {
g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC); g_critical ("%s: Unable to create an offscreen buffer", G_STRLOC);
cogl_object_unref (res->texture);
res->texture = NULL;
goto out; goto out;
} }
@@ -1446,15 +1458,14 @@ clutter_layer_node_new (const CoglMatrix *projection,
* interpolation filters because the texture is always * interpolation filters because the texture is always
* going to be painted at a 1:1 texel:pixel ratio * going to be painted at a 1:1 texel:pixel ratio
*/ */
res->pipeline = cogl_pipeline_copy (default_texture_pipeline); res->state = cogl_pipeline_copy (default_texture_pipeline);
cogl_pipeline_set_layer_filters (res->pipeline, 0, cogl_pipeline_set_layer_filters (res->state, 0,
COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST,
COGL_PIPELINE_FILTER_NEAREST); COGL_PIPELINE_FILTER_NEAREST);
cogl_pipeline_set_layer_texture (res->pipeline, 0, texture); cogl_pipeline_set_layer_texture (res->state, 0, res->texture);
cogl_pipeline_set_color (res->pipeline, &color); cogl_pipeline_set_color (res->state, &color);
cogl_object_unref (res->texture);
out: out:
cogl_object_unref (texture);
return (ClutterPaintNode *) res; return (ClutterPaintNode *) res;
} }

View File

@@ -62,7 +62,6 @@
#include "clutter-gesture-action-private.h" #include "clutter-gesture-action-private.h"
#include "clutter-marshal.h" #include "clutter-marshal.h"
#include "clutter-private.h" #include "clutter-private.h"
#include "clutter-timeline.h"
#include <math.h> #include <math.h>
#define FLOAT_EPSILON (1e-15) #define FLOAT_EPSILON (1e-15)
@@ -137,8 +136,7 @@ enum
static guint pan_signals[LAST_SIGNAL] = { 0, }; static guint pan_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action, G_DEFINE_TYPE_WITH_PRIVATE (ClutterPanAction, clutter_pan_action, CLUTTER_TYPE_GESTURE_ACTION)
CLUTTER_TYPE_GESTURE_ACTION)
static void static void
emit_pan (ClutterPanAction *self, emit_pan (ClutterPanAction *self,
@@ -158,18 +156,14 @@ emit_pan (ClutterPanAction *self,
gfloat scroll_threshold = G_PI_4/2; gfloat scroll_threshold = G_PI_4/2;
gfloat drag_angle; gfloat drag_angle;
clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), clutter_gesture_action_get_motion_delta (CLUTTER_GESTURE_ACTION (self), 0, &delta_x, &delta_y);
0,
&delta_x,
&delta_y);
if (delta_x != 0.0f) if (delta_x != 0.0f)
drag_angle = atanf (delta_y / delta_x); drag_angle = atanf (delta_y / delta_x);
else else
drag_angle = G_PI_2; drag_angle = G_PI_2;
if ((drag_angle > -scroll_threshold) && if ((drag_angle > -scroll_threshold) && (drag_angle < scroll_threshold))
(drag_angle < scroll_threshold))
priv->pin_state = SCROLL_PINNED_HORIZONTAL; priv->pin_state = SCROLL_PINNED_HORIZONTAL;
else if ((drag_angle > (G_PI_2 - scroll_threshold)) || else if ((drag_angle > (G_PI_2 - scroll_threshold)) ||
(drag_angle < -(G_PI_2 - scroll_threshold))) (drag_angle < -(G_PI_2 - scroll_threshold)))
@@ -288,10 +282,7 @@ gesture_end (ClutterGestureAction *gesture,
gfloat tau; gfloat tau;
gint duration; gint duration;
clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), clutter_gesture_action_get_release_coords (CLUTTER_GESTURE_ACTION (self), 0, &priv->release_x, &priv->release_y);
0,
&priv->release_x,
&priv->release_y);
if (!priv->should_interpolate) if (!priv->should_interpolate)
{ {
@@ -302,9 +293,7 @@ gesture_end (ClutterGestureAction *gesture,
priv->state = PAN_STATE_INTERPOLATING; priv->state = PAN_STATE_INTERPOLATING;
clutter_gesture_action_get_motion_delta (gesture, 0, &delta_x, &delta_y); clutter_gesture_action_get_motion_delta (gesture, 0, &delta_x, &delta_y);
velocity = clutter_gesture_action_get_velocity (gesture, 0, velocity = clutter_gesture_action_get_velocity (gesture, 0, &velocity_x, &velocity_y);
&velocity_x,
&velocity_y);
/* Exponential timing constant v(t) = v(0) * exp(-t/tau) /* Exponential timing constant v(t) = v(0) * exp(-t/tau)
* tau = 1000ms / (frame_per_second * - ln(decay_per_frame)) * tau = 1000ms / (frame_per_second * - ln(decay_per_frame))
@@ -315,26 +304,17 @@ gesture_end (ClutterGestureAction *gesture,
/* See where the decreasing velocity reaches $min_velocity px/ms /* See where the decreasing velocity reaches $min_velocity px/ms
* v(t) = v(0) * exp(-t/tau) = min_velocity * v(t) = v(0) * exp(-t/tau) = min_velocity
* t = - tau * ln( min_velocity / |v(0)|) */ * t = - tau * ln( min_velocity / |v(0)|) */
duration = - tau * logf (min_velocity / (ABS (velocity) * duration = - tau * logf (min_velocity / (ABS (velocity) * priv->acceleration_factor));
priv->acceleration_factor));
/* Target point: x(t) = v(0) * tau * [1 - exp(-t/tau)] */ /* Target point: x(t) = v(0) * tau * [1 - exp(-t/tau)] */
priv->target_x = (velocity_x * priv->acceleration_factor * tau * priv->target_x = velocity_x * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau));
(1 - exp ((float)-duration / tau))); priv->target_y = velocity_y * priv->acceleration_factor * tau * (1 - exp ((float)-duration / tau));
priv->target_y = (velocity_y * priv->acceleration_factor * tau *
(1 - exp ((float)-duration / tau)));
if (ABS (velocity) * priv->acceleration_factor > min_velocity && if (ABS (velocity) * priv->acceleration_factor > min_velocity && duration > FLOAT_EPSILON)
duration > FLOAT_EPSILON)
{ {
ClutterActor *pan_actor =
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gesture));
priv->interpolated_x = priv->interpolated_y = 0.0f; priv->interpolated_x = priv->interpolated_y = 0.0f;
priv->deceleration_timeline = clutter_timeline_new_for_actor (pan_actor, priv->deceleration_timeline = clutter_timeline_new (duration);
duration); clutter_timeline_set_progress_mode (priv->deceleration_timeline, CLUTTER_EASE_OUT_EXPO);
clutter_timeline_set_progress_mode (priv->deceleration_timeline,
CLUTTER_EASE_OUT_EXPO);
g_signal_connect (priv->deceleration_timeline, "new_frame", g_signal_connect (priv->deceleration_timeline, "new_frame",
G_CALLBACK (on_deceleration_new_frame), self); G_CALLBACK (on_deceleration_new_frame), self);
@@ -387,8 +367,7 @@ clutter_pan_action_set_property (GObject *gobject,
break; break;
case PROP_ACCELERATION_FACTOR : case PROP_ACCELERATION_FACTOR :
clutter_pan_action_set_acceleration_factor (self, clutter_pan_action_set_acceleration_factor (self, g_value_get_double (value));
g_value_get_double (value));
break; break;
default: default:
@@ -432,11 +411,9 @@ static void
clutter_pan_action_constructed (GObject *gobject) clutter_pan_action_constructed (GObject *gobject)
{ {
ClutterGestureAction *gesture; ClutterGestureAction *gesture;
ClutterGestureTriggerEdge edge;
gesture = CLUTTER_GESTURE_ACTION (gobject); gesture = CLUTTER_GESTURE_ACTION (gobject);
edge = CLUTTER_GESTURE_TRIGGER_EDGE_AFTER; clutter_gesture_action_set_threshold_trigger_edge (gesture, CLUTTER_GESTURE_TRIGGER_EDGE_AFTER);
clutter_gesture_action_set_threshold_trigger_edge (gesture, edge);
} }
static void static void
@@ -463,12 +440,9 @@ clutter_pan_action_set_actor (ClutterActorMeta *meta,
/* make sure we reset the state */ /* make sure we reset the state */
if (priv->state == PAN_STATE_INTERPOLATING) if (priv->state == PAN_STATE_INTERPOLATING)
g_clear_object (&priv->deceleration_timeline); g_clear_object (&priv->deceleration_timeline);
else if (priv->deceleration_timeline)
clutter_timeline_set_actor (priv->deceleration_timeline, actor);
} }
CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta, CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta, actor);
actor);
} }
@@ -906,9 +880,7 @@ clutter_pan_action_get_constrained_motion_delta (ClutterPanAction *self,
priv = self->priv; priv = self->priv;
distance = clutter_pan_action_get_motion_delta (self, point, distance = clutter_pan_action_get_motion_delta (self, point, &delta_x, &delta_y);
&delta_x,
&delta_y);
switch (priv->pan_axis) switch (priv->pan_axis)
{ {

View File

@@ -37,6 +37,7 @@
#include "clutter-feature.h" #include "clutter-feature.h"
#include "clutter-id-pool.h" #include "clutter-id-pool.h"
#include "clutter-layout-manager.h" #include "clutter-layout-manager.h"
#include "clutter-master-clock.h"
#include "clutter-settings.h" #include "clutter-settings.h"
#include "clutter-stage-manager.h" #include "clutter-stage-manager.h"
#include "clutter-stage.h" #include "clutter-stage.h"
@@ -64,6 +65,7 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#define CLUTTER_ACTOR_IS_TOPLEVEL(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IS_TOPLEVEL) != FALSE) #define CLUTTER_ACTOR_IS_TOPLEVEL(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IS_TOPLEVEL) != FALSE)
#define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) != FALSE) #define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) != FALSE)
#define CLUTTER_ACTOR_IN_REPARENT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_REPARENT) != FALSE)
#define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE) #define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE)
#define CLUTTER_ACTOR_IN_PICK(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PICK) != FALSE) #define CLUTTER_ACTOR_IN_PICK(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PICK) != FALSE)
#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE) #define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE)
@@ -97,6 +99,7 @@ typedef enum
CLUTTER_IN_DESTRUCTION = 1 << 0, CLUTTER_IN_DESTRUCTION = 1 << 0,
CLUTTER_IS_TOPLEVEL = 1 << 1, CLUTTER_IS_TOPLEVEL = 1 << 1,
CLUTTER_IN_REPARENT = 1 << 2,
CLUTTER_IN_PREF_WIDTH = 1 << 3, CLUTTER_IN_PREF_WIDTH = 1 << 3,
CLUTTER_IN_PREF_HEIGHT = 1 << 4, CLUTTER_IN_PREF_HEIGHT = 1 << 4,
@@ -121,6 +124,9 @@ struct _ClutterMainContext
/* the object holding all the stage instances */ /* the object holding all the stage instances */
ClutterStageManager *stage_manager; ClutterStageManager *stage_manager;
/* the clock driving all the frame operations */
ClutterMasterClock *master_clock;
/* the main event queue */ /* the main event queue */
GQueue *events_queue; GQueue *events_queue;
@@ -173,6 +179,11 @@ typedef struct
gboolean _clutter_threads_dispatch (gpointer data); gboolean _clutter_threads_dispatch (gpointer data);
void _clutter_threads_dispatch_free (gpointer data); void _clutter_threads_dispatch_free (gpointer data);
CLUTTER_EXPORT
void _clutter_threads_acquire_lock (void);
CLUTTER_EXPORT
void _clutter_threads_release_lock (void);
ClutterMainContext * _clutter_context_get_default (void); ClutterMainContext * _clutter_context_get_default (void);
void _clutter_context_lock (void); void _clutter_context_lock (void);
void _clutter_context_unlock (void); void _clutter_context_unlock (void);
@@ -307,30 +318,6 @@ gboolean _clutter_run_progress_function (GType gtype,
void clutter_timeline_cancel_delay (ClutterTimeline *timeline); void clutter_timeline_cancel_delay (ClutterTimeline *timeline);
static inline uint64_t
us (uint64_t us)
{
return us;
}
static inline uint64_t
ms2us (uint64_t ms)
{
return us (ms * 1000);
}
static inline uint32_t
us2ms (uint64_t us)
{
return (uint32_t) (us / 1000);
}
static inline uint64_t
ns2us (uint64_t ns)
{
return us (ns / 1000);
}
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_PRIVATE_H__ */ #endif /* __CLUTTER_PRIVATE_H__ */

View File

@@ -278,26 +278,6 @@ clutter_property_transition_init (ClutterPropertyTransition *self)
self->priv = clutter_property_transition_get_instance_private (self); self->priv = clutter_property_transition_get_instance_private (self);
} }
/**
* clutter_property_transition_new_for_actor:
* @actor: a #ClutterActor
* @property_name: (allow-none): a property of @animatable, or %NULL
*
* Creates a new #ClutterPropertyTransition.
*
* Return value: (transfer full): the newly created #ClutterPropertyTransition.
* Use g_object_unref() when done
*/
ClutterTransition *
clutter_property_transition_new_for_actor (ClutterActor *actor,
const char *property_name)
{
return g_object_new (CLUTTER_TYPE_PROPERTY_TRANSITION,
"actor", actor,
"property-name", property_name,
NULL);
}
/** /**
* clutter_property_transition_new: * clutter_property_transition_new:
* @property_name: (allow-none): a property of @animatable, or %NULL * @property_name: (allow-none): a property of @animatable, or %NULL

View File

@@ -78,13 +78,8 @@ struct _ClutterPropertyTransitionClass
CLUTTER_EXPORT CLUTTER_EXPORT
GType clutter_property_transition_get_type (void) G_GNUC_CONST; GType clutter_property_transition_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterTransition * clutter_property_transition_new_for_actor (ClutterActor *actor,
const char *property_name);
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterTransition * clutter_property_transition_new (const char *property_name); ClutterTransition * clutter_property_transition_new (const char *property_name);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition, void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition,
const char *property_name); const char *property_name);

View File

@@ -34,6 +34,7 @@
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-container.h" #include "deprecated/clutter-container.h"
#include "deprecated/clutter-alpha.h"
#include "clutter-actor.h" #include "clutter-actor.h"
#include "clutter-debug.h" #include "clutter-debug.h"
@@ -798,6 +799,232 @@ parse_signals (ClutterScript *script,
return retval; return retval;
} }
static ClutterTimeline *
construct_timeline (ClutterScript *script,
JsonObject *object)
{
ClutterTimeline *retval = NULL;
ObjectInfo *oinfo;
GList *members, *l;
/* we fake an ObjectInfo so we can reuse clutter_script_construct_object()
* here; we do not save it inside the hash table, because if this had
* been a named object then we wouldn't have ended up here in the first
* place
*/
oinfo = g_slice_new0 (ObjectInfo);
oinfo->gtype = CLUTTER_TYPE_TIMELINE;
oinfo->id = g_strdup ("dummy");
members = json_object_get_members (object);
for (l = members; l != NULL; l = l->next)
{
const gchar *name = l->data;
JsonNode *node = json_object_get_member (object, name);
PropertyInfo *pinfo = g_slice_new0 (PropertyInfo);
pinfo->name = g_strdelimit (g_strdup (name), G_STR_DELIMITERS, '-');
pinfo->node = json_node_copy (node);
oinfo->properties = g_list_prepend (oinfo->properties, pinfo);
}
g_list_free (members);
_clutter_script_construct_object (script, oinfo);
_clutter_script_apply_properties (script, oinfo);
retval = CLUTTER_TIMELINE (oinfo->object);
/* we transfer ownership to the alpha function, so we ref before
* destroying the ObjectInfo to avoid the timeline going away
*/
g_object_ref (retval);
object_info_free (oinfo);
return retval;
}
/* define the names of the animation modes to match the ones
* that developers might be more accustomed to
*/
static const struct
{
const gchar *name;
ClutterAnimationMode mode;
} animation_modes[] = {
{ "linear", CLUTTER_LINEAR },
{ "easeInQuad", CLUTTER_EASE_IN_QUAD },
{ "easeOutQuad", CLUTTER_EASE_OUT_QUAD },
{ "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD },
{ "easeInCubic", CLUTTER_EASE_IN_CUBIC },
{ "easeOutCubic", CLUTTER_EASE_OUT_CUBIC },
{ "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC },
{ "easeInQuart", CLUTTER_EASE_IN_QUART },
{ "easeOutQuart", CLUTTER_EASE_OUT_QUART },
{ "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART },
{ "easeInQuint", CLUTTER_EASE_IN_QUINT },
{ "easeOutQuint", CLUTTER_EASE_OUT_QUINT },
{ "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT },
{ "easeInSine", CLUTTER_EASE_IN_SINE },
{ "easeOutSine", CLUTTER_EASE_OUT_SINE },
{ "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE },
{ "easeInExpo", CLUTTER_EASE_IN_EXPO },
{ "easeOutExpo", CLUTTER_EASE_OUT_EXPO },
{ "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO },
{ "easeInCirc", CLUTTER_EASE_IN_CIRC },
{ "easeOutCirc", CLUTTER_EASE_OUT_CIRC },
{ "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC },
{ "easeInElastic", CLUTTER_EASE_IN_ELASTIC },
{ "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC },
{ "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC },
{ "easeInBack", CLUTTER_EASE_IN_BACK },
{ "easeOutBack", CLUTTER_EASE_OUT_BACK },
{ "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK },
{ "easeInBounce", CLUTTER_EASE_IN_BOUNCE },
{ "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE },
{ "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE },
};
static const gint n_animation_modes = G_N_ELEMENTS (animation_modes);
gulong
_clutter_script_resolve_animation_mode (JsonNode *node)
{
gint i, res = CLUTTER_CUSTOM_MODE;
if (JSON_NODE_TYPE (node) != JSON_NODE_VALUE)
return CLUTTER_CUSTOM_MODE;
if (json_node_get_value_type (node) == G_TYPE_INT64)
return json_node_get_int (node);
if (json_node_get_value_type (node) == G_TYPE_STRING)
{
const gchar *name = json_node_get_string (node);
/* XXX - we might be able to optimize by changing the ordering
* of the animation_modes array, e.g.
* - special casing linear
* - tokenizing ('ease', 'In', 'Sine') and matching on token
* - binary searching?
*/
for (i = 0; i < n_animation_modes; i++)
{
if (strcmp (animation_modes[i].name, name) == 0)
return animation_modes[i].mode;
}
if (_clutter_script_enum_from_string (CLUTTER_TYPE_ANIMATION_MODE,
name,
&res))
return res;
g_warning ("Unable to find the animation mode '%s'", name);
}
return CLUTTER_CUSTOM_MODE;
}
static ClutterAlphaFunc
resolve_alpha_func (const gchar *name)
{
static GModule *module = NULL;
ClutterAlphaFunc func;
CLUTTER_NOTE (SCRIPT, "Looking up '%s' alpha function", name);
if (G_UNLIKELY (!module))
module = g_module_open (NULL, 0);
if (g_module_symbol (module, name, (gpointer) &func))
{
CLUTTER_NOTE (SCRIPT, "Found '%s' alpha function in the symbols table",
name);
return func;
}
return NULL;
}
GObject *
_clutter_script_parse_alpha (ClutterScript *script,
JsonNode *node)
{
GObject *retval = NULL;
JsonObject *object;
ClutterTimeline *timeline = NULL;
ClutterAlphaFunc alpha_func = NULL;
ClutterAnimationMode mode = CLUTTER_CUSTOM_MODE;
JsonNode *val;
gboolean unref_timeline = FALSE;
if (JSON_NODE_TYPE (node) != JSON_NODE_OBJECT)
return NULL;
object = json_node_get_object (node);
val = json_object_get_member (object, "timeline");
if (val)
{
if (JSON_NODE_TYPE (val) == JSON_NODE_VALUE &&
json_node_get_string (val) != NULL)
{
const gchar *id_ = json_node_get_string (val);
timeline =
CLUTTER_TIMELINE (clutter_script_get_object (script, id_));
}
else if (JSON_NODE_TYPE (val) == JSON_NODE_OBJECT)
{
timeline = construct_timeline (script, json_node_get_object (val));
unref_timeline = TRUE;
}
}
val = json_object_get_member (object, "mode");
if (val != NULL)
mode = _clutter_script_resolve_animation_mode (val);
if (mode == CLUTTER_CUSTOM_MODE)
{
val = json_object_get_member (object, "function");
if (val && json_node_get_string (val) != NULL)
{
alpha_func = resolve_alpha_func (json_node_get_string (val));
if (!alpha_func)
{
g_warning ("Unable to find the function '%s' in the "
"Clutter alpha functions or the symbols table",
json_node_get_string (val));
}
}
}
CLUTTER_NOTE (SCRIPT, "Parsed alpha: %s timeline (%p) (mode:%d, func:%p)",
unref_timeline ? "implicit" : "explicit",
timeline ? timeline : 0x0,
mode != CLUTTER_CUSTOM_MODE ? mode : 0,
alpha_func ? alpha_func : 0x0);
retval = g_object_new (CLUTTER_TYPE_ALPHA, NULL);
if (mode != CLUTTER_CUSTOM_MODE)
clutter_alpha_set_mode (CLUTTER_ALPHA (retval), mode);
if (alpha_func != NULL)
clutter_alpha_set_func (CLUTTER_ALPHA (retval), alpha_func, NULL, NULL);
clutter_alpha_set_timeline (CLUTTER_ALPHA (retval), timeline);
/* if we created an implicit timeline, the Alpha has full ownership
* of it now, since it won't be accessible from ClutterScript
*/
if (unref_timeline)
g_object_unref (timeline);
return retval;
}
static void static void
clutter_script_parser_object_end (JsonParser *json_parser, clutter_script_parser_object_end (JsonParser *json_parser,
JsonObject *object) JsonObject *object)
@@ -1523,7 +1750,7 @@ clutter_script_construct_parameters (ClutterScript *script,
continue; continue;
} }
if (!(pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))) if (!(pspec->flags & G_PARAM_CONSTRUCT_ONLY))
{ {
unparsed = g_list_prepend (unparsed, pinfo); unparsed = g_list_prepend (unparsed, pinfo);
continue; continue;

View File

@@ -110,6 +110,8 @@ gboolean _clutter_script_parse_node (ClutterScript *script,
GType _clutter_script_get_type_from_symbol (const gchar *symbol); GType _clutter_script_get_type_from_symbol (const gchar *symbol);
GType _clutter_script_get_type_from_class (const gchar *name); GType _clutter_script_get_type_from_class (const gchar *name);
gulong _clutter_script_resolve_animation_mode (JsonNode *node);
gboolean _clutter_script_enum_from_string (GType gtype, gboolean _clutter_script_enum_from_string (GType gtype,
const gchar *string, const gchar *string,
gint *enum_value); gint *enum_value);
@@ -126,6 +128,8 @@ gboolean _clutter_script_parse_rect (ClutterScript *script,
gboolean _clutter_script_parse_color (ClutterScript *script, gboolean _clutter_script_parse_color (ClutterScript *script,
JsonNode *node, JsonNode *node,
ClutterColor *color); ClutterColor *color);
GObject *_clutter_script_parse_alpha (ClutterScript *script,
JsonNode *node);
gboolean _clutter_script_parse_point (ClutterScript *script, gboolean _clutter_script_parse_point (ClutterScript *script,
JsonNode *node, JsonNode *node,
graphene_point_t *point); graphene_point_t *point);

View File

@@ -50,14 +50,14 @@
* <informalexample><programlisting><![CDATA[ * <informalexample><programlisting><![CDATA[
* { * {
* "id" : "red-button", * "id" : "red-button",
* "type" : "ClutterActor", * "type" : "ClutterRectangle",
* "width" : 100, * "width" : 100,
* "height" : 100, * "height" : 100,
* "background-color" : "&num;ff0000ff" * "color" : "&num;ff0000ff"
* } * }
* ]]></programlisting></informalexample> * ]]></programlisting></informalexample>
* *
* This will produce a red #ClutterActor, 100x100 pixels wide, and * This will produce a red #ClutterRectangle, 100x100 pixels wide, and
* with a ClutterScript id of "red-button"; it can be retrieved by calling: * with a ClutterScript id of "red-button"; it can be retrieved by calling:
* *
* |[ * |[
@@ -98,6 +98,49 @@
* respectively) and the "object" string member for calling * respectively) and the "object" string member for calling
* g_signal_connect_object() instead of g_signal_connect(). * g_signal_connect_object() instead of g_signal_connect().
* *
* Signals can also be directly attached to a specific state defined
* inside a #ClutterState instance, for instance:
*
* |[
* ...
* "signals" : [
* {
* "name" : "enter-event",
* "states" : "button-states",
* "target-state" : "hover"
* },
* {
* "name" : "leave-event",
* "states" : "button-states",
* "target-state" : "base"
* },
* {
* "name" : "button-press-event",
* "states" : "button-states",
* "target-state" : "active",
* },
* {
* "name" : "key-press-event",
* "states" : "button-states",
* "target-state" : "key-focus",
* "warp" : true
* }
* ],
* ...
* ]|
*
* The "states" key defines the #ClutterState instance to be used to
* resolve the "target-state" key; it can be either a script id for a
* #ClutterState built by the same #ClutterScript instance, or to a
* #ClutterState built in code and associated to the #ClutterScript
* instance through the clutter_script_add_states() function. If no
* "states" key is present, then the default #ClutterState associated to
* the #ClutterScript instance will be used; the default #ClutterState
* can be set using clutter_script_add_states() using a %NULL name. The
* "warp" key can be used to warp to a specific state instead of
* animating to it. State changes on signal emission will not affect
* the signal emission chain.
*
* Clutter reserves the following names, so classes defining properties * Clutter reserves the following names, so classes defining properties
* through the usual GObject registration process should avoid using these * through the usual GObject registration process should avoid using these
* names to avoid collisions: * names to avoid collisions:
@@ -141,7 +184,9 @@
#include "clutter-private.h" #include "clutter-private.h"
#include "clutter-debug.h" #include "clutter-debug.h"
#include "deprecated/clutter-alpha.h"
#include "deprecated/clutter-container.h" #include "deprecated/clutter-container.h"
#include "deprecated/clutter-state.h"
enum enum
{ {
@@ -165,6 +210,8 @@ struct _ClutterScriptPrivate
ClutterScriptParser *parser; ClutterScriptParser *parser;
GHashTable *states;
gchar **search_paths; gchar **search_paths;
gchar *translation_domain; gchar *translation_domain;
@@ -217,6 +264,7 @@ signal_info_free (gpointer data)
g_free (sinfo->name); g_free (sinfo->name);
g_free (sinfo->handler); g_free (sinfo->handler);
g_free (sinfo->object); g_free (sinfo->object);
g_free (sinfo->state);
g_free (sinfo->target); g_free (sinfo->target);
g_slice_free (SignalInfo, sinfo); g_slice_free (SignalInfo, sinfo);
@@ -271,6 +319,7 @@ clutter_script_finalize (GObject *gobject)
g_hash_table_destroy (priv->objects); g_hash_table_destroy (priv->objects);
g_strfreev (priv->search_paths); g_strfreev (priv->search_paths);
g_free (priv->filename); g_free (priv->filename);
g_hash_table_destroy (priv->states);
g_free (priv->translation_domain); g_free (priv->translation_domain);
G_OBJECT_CLASS (clutter_script_parent_class)->finalize (gobject); G_OBJECT_CLASS (clutter_script_parent_class)->finalize (gobject);
@@ -405,6 +454,9 @@ clutter_script_init (ClutterScript *script)
priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal, priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, NULL,
object_info_free); object_info_free);
priv->states = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify) g_object_unref);
} }
/** /**
@@ -920,12 +972,65 @@ clutter_script_connect_signals (ClutterScript *script,
g_free (cd); g_free (cd);
} }
typedef struct {
ClutterState *state;
GObject *emitter;
gchar *target;
gulong signal_id;
gulong hook_id;
gboolean warp_to;
} HookData;
typedef struct { typedef struct {
ClutterScript *script; ClutterScript *script;
ClutterScriptConnectFunc func; ClutterScriptConnectFunc func;
gpointer user_data; gpointer user_data;
} SignalConnectData; } SignalConnectData;
static void
hook_data_free (gpointer data)
{
if (G_LIKELY (data != NULL))
{
HookData *hook_data = data;
g_free (hook_data->target);
g_slice_free (HookData, hook_data);
}
}
static gboolean
clutter_script_state_change_hook (GSignalInvocationHint *ihint,
guint n_params,
const GValue *params,
gpointer user_data)
{
HookData *hook_data = user_data;
GObject *emitter;
emitter = g_value_get_object (&params[0]);
if (emitter == hook_data->emitter)
{
if (hook_data->warp_to)
clutter_state_warp_to_state (hook_data->state, hook_data->target);
else
clutter_state_set_state (hook_data->state, hook_data->target);
}
return TRUE;
}
static void
clutter_script_remove_state_change_hook (gpointer user_data,
GObject *object_p)
{
HookData *hook_data = user_data;
g_signal_remove_emission_hook (hook_data->signal_id,
hook_data->hook_id);
}
static void static void
connect_each_object (gpointer key, connect_each_object (gpointer key,
gpointer value, gpointer value,
@@ -965,7 +1070,64 @@ connect_each_object (gpointer key,
} }
else else
{ {
g_warn_if_reached (); GObject *state_object = NULL;
const gchar *signal_name, *signal_detail;
gchar **components;
GQuark signal_quark;
guint signal_id;
HookData *hook_data;
if (sinfo->state == NULL)
state_object = (GObject *) clutter_script_get_states (script, NULL);
else
{
state_object = clutter_script_get_object (script, sinfo->state);
if (state_object == NULL)
state_object = (GObject *) clutter_script_get_states (script, sinfo->state);
}
if (state_object == NULL)
continue;
components = g_strsplit (sinfo->name, "::", 2);
if (g_strv_length (components) == 2)
{
signal_name = components[0];
signal_detail = components[1];
}
else
{
signal_name = components[0];
signal_detail = NULL;
}
signal_id = g_signal_lookup (signal_name, G_OBJECT_TYPE (object));
if (signal_id == 0)
{
g_strfreev (components);
continue;
}
if (signal_detail != NULL)
signal_quark = g_quark_from_string (signal_detail);
else
signal_quark = 0;
hook_data = g_slice_new (HookData);
hook_data->emitter = object;
hook_data->state = CLUTTER_STATE (state_object);
hook_data->target = g_strdup (sinfo->target);
hook_data->warp_to = sinfo->warp_to;
hook_data->signal_id = signal_id;
hook_data->hook_id =
g_signal_add_emission_hook (signal_id, signal_quark,
clutter_script_state_change_hook,
hook_data,
hook_data_free);
g_object_weak_ref (hook_data->emitter,
clutter_script_remove_state_change_hook,
hook_data);
} }
signal_info_free (sinfo); signal_info_free (sinfo);
@@ -1190,6 +1352,72 @@ clutter_script_list_objects (ClutterScript *script)
return retval; return retval;
} }
/**
* clutter_script_add_states:
* @script: a #ClutterScript
* @name: (allow-none): a name for the @state, or %NULL to
* set the default #ClutterState
* @state: a #ClutterState
*
* Associates a #ClutterState to the #ClutterScript instance using the given
* name.
*
* The #ClutterScript instance will use @state to resolve target states when
* connecting signal handlers.
*
* The #ClutterScript instance will take a reference on the #ClutterState
* passed to this function.
*
* Since: 1.8
*
* Deprecated: 1.12
*/
void
clutter_script_add_states (ClutterScript *script,
const gchar *name,
ClutterState *state)
{
g_return_if_fail (CLUTTER_IS_SCRIPT (script));
g_return_if_fail (CLUTTER_IS_STATE (state));
if (name == NULL || *name == '\0')
name = "__clutter_script_default_state";
g_hash_table_replace (script->priv->states,
g_strdup (name),
g_object_ref (state));
}
/**
* clutter_script_get_states:
* @script: a #ClutterScript
* @name: (allow-none): the name of the #ClutterState, or %NULL
*
* Retrieves the #ClutterState for the given @state_name.
*
* If @name is %NULL, this function will return the default
* #ClutterState instance.
*
* Return value: (transfer none): a pointer to the #ClutterState for the
* given name. The #ClutterState is owned by the #ClutterScript instance
* and it should not be unreferenced
*
* Since: 1.8
*
* Deprecated: 1.12
*/
ClutterState *
clutter_script_get_states (ClutterScript *script,
const gchar *name)
{
g_return_val_if_fail (CLUTTER_IS_SCRIPT (script), NULL);
if (name == NULL || *name == '\0')
name = "__clutter_script_default_state";
return g_hash_table_lookup (script->priv->states, name);
}
/** /**
* clutter_script_set_translation_domain: * clutter_script_set_translation_domain:
* @script: a #ClutterScript * @script: a #ClutterScript

View File

@@ -179,6 +179,15 @@ void clutter_script_unmerge_objects (ClutterScript
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_script_ensure_objects (ClutterScript *script); void clutter_script_ensure_objects (ClutterScript *script);
CLUTTER_DEPRECATED
void clutter_script_add_states (ClutterScript *script,
const gchar *name,
ClutterState *state);
CLUTTER_DEPRECATED
ClutterState * clutter_script_get_states (ClutterScript *script,
const gchar *name);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_script_connect_signals (ClutterScript *script, void clutter_script_connect_signals (ClutterScript *script,
gpointer user_data); gpointer user_data);

View File

@@ -354,17 +354,6 @@ clutter_seat_get_keyboard (ClutterSeat *seat)
return CLUTTER_SEAT_GET_CLASS (seat)->get_keyboard (seat); return CLUTTER_SEAT_GET_CLASS (seat)->get_keyboard (seat);
} }
/**
* clutter_seat_peek_devices: (skip)
**/
const GList *
clutter_seat_peek_devices (ClutterSeat *seat)
{
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL);
return CLUTTER_SEAT_GET_CLASS (seat)->peek_devices (seat);
}
/** /**
* clutter_seat_list_devices: * clutter_seat_list_devices:
* @seat: a #ClutterSeat * @seat: a #ClutterSeat
@@ -381,7 +370,7 @@ clutter_seat_list_devices (ClutterSeat *seat)
{ {
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL); g_return_val_if_fail (CLUTTER_IS_SEAT (seat), NULL);
return g_list_copy ((GList *)clutter_seat_peek_devices (seat)); return CLUTTER_SEAT_GET_CLASS (seat)->list_devices (seat);
} }
void void
@@ -645,8 +634,8 @@ clutter_seat_create_virtual_device (ClutterSeat *seat,
} }
/** /**
* clutter_seat_get_supported_virtual_device_types: (skip) * clutter_seat_supported_virtual_device_types: (skip)
**/ */
ClutterVirtualDeviceType ClutterVirtualDeviceType
clutter_seat_get_supported_virtual_device_types (ClutterSeat *seat) clutter_seat_get_supported_virtual_device_types (ClutterSeat *seat)
{ {
@@ -693,6 +682,7 @@ clutter_seat_warp_pointer (ClutterSeat *seat,
* requirements are fulfilled: * requirements are fulfilled:
* *
* - A touchscreen is available * - A touchscreen is available
* - No external keyboard is attached to the device
* - A tablet mode switch, if present, is enabled * - A tablet mode switch, if present, is enabled
* *
* Returns: %TRUE if the device is a tablet that doesn't have an external * Returns: %TRUE if the device is a tablet that doesn't have an external

View File

@@ -96,7 +96,7 @@ struct _ClutterSeatClass
ClutterInputDevice * (* get_pointer) (ClutterSeat *seat); ClutterInputDevice * (* get_pointer) (ClutterSeat *seat);
ClutterInputDevice * (* get_keyboard) (ClutterSeat *seat); ClutterInputDevice * (* get_keyboard) (ClutterSeat *seat);
const GList * (* peek_devices) (ClutterSeat *seat); GList * (* list_devices) (ClutterSeat *seat);
void (* bell_notify) (ClutterSeat *seat); void (* bell_notify) (ClutterSeat *seat);
@@ -133,7 +133,6 @@ CLUTTER_EXPORT
ClutterInputDevice * clutter_seat_get_keyboard (ClutterSeat *seat); ClutterInputDevice * clutter_seat_get_keyboard (ClutterSeat *seat);
CLUTTER_EXPORT CLUTTER_EXPORT
GList * clutter_seat_list_devices (ClutterSeat *seat); GList * clutter_seat_list_devices (ClutterSeat *seat);
const GList * clutter_seat_peek_devices (ClutterSeat *seat);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_seat_bell_notify (ClutterSeat *seat); void clutter_seat_bell_notify (ClutterSeat *seat);

View File

@@ -40,14 +40,7 @@ void clutter_stage_paint_view (ClutterStage
ClutterStageView *view, ClutterStageView *view,
const cairo_region_t *redraw_clip); const cairo_region_t *redraw_clip);
void clutter_stage_emit_before_update (ClutterStage *stage, void _clutter_stage_emit_after_paint (ClutterStage *stage);
ClutterStageView *view);
void clutter_stage_emit_before_paint (ClutterStage *stage,
ClutterStageView *view);
void clutter_stage_emit_after_paint (ClutterStage *stage,
ClutterStageView *view);
void clutter_stage_emit_after_update (ClutterStage *stage,
ClutterStageView *view);
CLUTTER_EXPORT CLUTTER_EXPORT
void _clutter_stage_set_window (ClutterStage *stage, void _clutter_stage_set_window (ClutterStage *stage,
@@ -57,6 +50,11 @@ ClutterStageWindow *_clutter_stage_get_window (ClutterStage
void _clutter_stage_get_projection_matrix (ClutterStage *stage, void _clutter_stage_get_projection_matrix (ClutterStage *stage,
CoglMatrix *projection); CoglMatrix *projection);
void _clutter_stage_dirty_projection (ClutterStage *stage); void _clutter_stage_dirty_projection (ClutterStage *stage);
void _clutter_stage_set_viewport (ClutterStage *stage,
float x,
float y,
float width,
float height);
void _clutter_stage_get_viewport (ClutterStage *stage, void _clutter_stage_get_viewport (ClutterStage *stage,
float *x, float *x,
float *y, float *y,
@@ -65,12 +63,9 @@ void _clutter_stage_get_viewport (ClutterStage
void _clutter_stage_dirty_viewport (ClutterStage *stage); void _clutter_stage_dirty_viewport (ClutterStage *stage);
void _clutter_stage_maybe_setup_viewport (ClutterStage *stage, void _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
ClutterStageView *view); ClutterStageView *view);
void clutter_stage_maybe_relayout (ClutterActor *stage); void _clutter_stage_maybe_relayout (ClutterActor *stage);
void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage); gboolean _clutter_stage_needs_update (ClutterStage *stage);
GSList * clutter_stage_find_updated_devices (ClutterStage *stage); gboolean _clutter_stage_do_update (ClutterStage *stage);
void clutter_stage_update_devices (ClutterStage *stage,
GSList *devices);
void clutter_stage_update_actor_stage_views (ClutterStage *stage);
CLUTTER_EXPORT CLUTTER_EXPORT
void _clutter_stage_queue_event (ClutterStage *stage, void _clutter_stage_queue_event (ClutterStage *stage,
@@ -79,7 +74,11 @@ void _clutter_stage_queue_event (ClutterStage *stage,
gboolean _clutter_stage_has_queued_events (ClutterStage *stage); gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
void _clutter_stage_process_queued_events (ClutterStage *stage); void _clutter_stage_process_queued_events (ClutterStage *stage);
void _clutter_stage_update_input_devices (ClutterStage *stage); void _clutter_stage_update_input_devices (ClutterStage *stage);
void _clutter_stage_schedule_update (ClutterStage *stage);
gint64 _clutter_stage_get_update_time (ClutterStage *stage);
void _clutter_stage_clear_update_time (ClutterStage *stage);
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage); gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
int64_t _clutter_stage_get_next_presentation_time (ClutterStage *stage);
void clutter_stage_log_pick (ClutterStage *stage, void clutter_stage_log_pick (ClutterStage *stage,
const graphene_point_t *vertices, const graphene_point_t *vertices,
@@ -133,19 +132,19 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
void _clutter_stage_set_scale_factor (ClutterStage *stage, void _clutter_stage_set_scale_factor (ClutterStage *stage,
int factor); int factor);
gboolean _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
graphene_rect_t *rect,
float *view_scale);
void clutter_stage_presented (ClutterStage *stage, void _clutter_stage_presented (ClutterStage *stage,
ClutterStageView *view, CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info); ClutterFrameInfo *frame_info);
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
void clutter_stage_queue_actor_relayout (ClutterStage *stage, void clutter_stage_queue_actor_relayout (ClutterStage *stage,
ClutterActor *actor); ClutterActor *actor);
GList * clutter_stage_get_views_for_rect (ClutterStage *stage,
const graphene_rect_t *rect);
void clutter_stage_set_actor_needs_immediate_relayout (ClutterStage *stage);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */ #endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View File

@@ -19,30 +19,18 @@
#define __CLUTTER_STAGE_VIEW_PRIVATE_H__ #define __CLUTTER_STAGE_VIEW_PRIVATE_H__
#include "clutter/clutter-stage-view.h" #include "clutter/clutter-stage-view.h"
#include "clutter/clutter-types.h"
void clutter_stage_view_after_paint (ClutterStageView *view, void clutter_stage_view_after_paint (ClutterStageView *view);
cairo_region_t *redraw_clip);
void clutter_stage_view_before_swap_buffer (ClutterStageView *view,
const cairo_region_t *swap_region);
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view); gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
void clutter_stage_view_invalidate_viewport (ClutterStageView *view); void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
gboolean dirty);
void clutter_stage_view_set_viewport (ClutterStageView *view,
float x,
float y,
float width,
float height);
gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view); gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
void clutter_stage_view_invalidate_projection (ClutterStageView *view); void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
gboolean dirty);
void clutter_stage_view_set_projection (ClutterStageView *view,
const CoglMatrix *matrix);
void clutter_stage_view_add_redraw_clip (ClutterStageView *view, void clutter_stage_view_add_redraw_clip (ClutterStageView *view,
const cairo_rectangle_int_t *clip); const cairo_rectangle_int_t *clip);
@@ -55,20 +43,4 @@ const cairo_region_t * clutter_stage_view_peek_redraw_clip (ClutterStageView *vi
cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view); cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view);
CoglScanout * clutter_stage_view_take_scanout (ClutterStageView *view);
void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view,
const cairo_rectangle_int_t *src_rect,
int dst_width,
int dst_height,
cairo_rectangle_int_t *dst_rect);
void clutter_stage_view_schedule_update (ClutterStageView *view);
CLUTTER_EXPORT
float clutter_stage_view_get_refresh_rate (ClutterStageView *view);
void clutter_stage_view_notify_presented (ClutterStageView *view,
ClutterFrameInfo *frame_info);
#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */ #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,6 @@
#include <cogl/cogl.h> #include <cogl/cogl.h>
#include "clutter-macros.h" #include "clutter-macros.h"
#include "clutter-frame-clock.h"
#define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ()) #define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ())
CLUTTER_EXPORT CLUTTER_EXPORT
@@ -44,12 +43,6 @@ struct _ClutterStageViewClass
void (* get_offscreen_transformation_matrix) (ClutterStageView *view, void (* get_offscreen_transformation_matrix) (ClutterStageView *view,
CoglMatrix *matrix); CoglMatrix *matrix);
void (* transform_rect_to_onscreen) (ClutterStageView *view,
const cairo_rectangle_int_t *src_rect,
int dst_width,
int dst_height,
cairo_rectangle_int_t *dst_rect);
}; };
CLUTTER_EXPORT CLUTTER_EXPORT
@@ -63,6 +56,11 @@ CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view); void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view);
CLUTTER_EXPORT
void clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
gfloat *x,
gfloat *y);
CLUTTER_EXPORT CLUTTER_EXPORT
float clutter_stage_view_get_scale (ClutterStageView *view); float clutter_stage_view_get_scale (ClutterStageView *view);
@@ -70,7 +68,4 @@ CLUTTER_EXPORT
void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view, void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
CoglMatrix *matrix); CoglMatrix *matrix);
CLUTTER_EXPORT
ClutterFrameClock * clutter_stage_view_get_frame_clock (ClutterStageView *view);
#endif /* __CLUTTER_STAGE_VIEW_H__ */ #endif /* __CLUTTER_STAGE_VIEW_H__ */

View File

@@ -62,6 +62,16 @@ _clutter_stage_window_set_title (ClutterStageWindow *window,
iface->set_title (window, title); iface->set_title (window, title);
} }
void
_clutter_stage_window_set_cursor_visible (ClutterStageWindow *window,
gboolean is_visible)
{
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->set_cursor_visible)
iface->set_cursor_visible (window, is_visible);
}
gboolean gboolean
_clutter_stage_window_realize (ClutterStageWindow *window) _clutter_stage_window_realize (ClutterStageWindow *window)
{ {
@@ -103,12 +113,110 @@ _clutter_stage_window_get_geometry (ClutterStageWindow *window,
} }
void void
_clutter_stage_window_redraw_view (ClutterStageWindow *window, _clutter_stage_window_schedule_update (ClutterStageWindow *window,
ClutterStageView *view) int sync_delay)
{ {
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window)); g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view); iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->schedule_update == NULL)
{
g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
return;
}
iface->schedule_update (window, sync_delay);
}
/**
* _clutter_stage_window_get_update_time:
* @window: a #ClutterStageWindow object
*
* See _clutter_stage_get_update_time() for more info.
*
* Returns: The timestamp of the update time
*/
gint64
_clutter_stage_window_get_update_time (ClutterStageWindow *window)
{
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0);
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->get_update_time == NULL)
{
g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
return 0;
}
return iface->get_update_time (window);
}
/**
* _clutter_stage_window_clear_update_time:
* @window: a #ClutterStageWindow object
*
* Clears the update time. See _clutter_stage_clear_update_time() for more info.
*/
void
_clutter_stage_window_clear_update_time (ClutterStageWindow *window)
{
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->clear_update_time == NULL)
{
g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
return;
}
iface->clear_update_time (window);
}
int64_t
_clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window)
{
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0);
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
/* If not implemented then just revert to the old behaviour... */
if (iface->get_next_presentation_time == NULL)
return _clutter_stage_window_get_update_time (window);
return iface->get_next_presentation_time (window);
}
void
_clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus)
{
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->set_accept_focus)
iface->set_accept_focus (window, accept_focus);
}
void
_clutter_stage_window_redraw (ClutterStageWindow *window)
{
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->redraw)
iface->redraw (window);
} }
gboolean gboolean

View File

@@ -30,6 +30,8 @@ struct _ClutterStageWindowInterface
void (* set_title) (ClutterStageWindow *stage_window, void (* set_title) (ClutterStageWindow *stage_window,
const gchar *title); const gchar *title);
void (* set_cursor_visible) (ClutterStageWindow *stage_window,
gboolean cursor_visible);
gboolean (* realize) (ClutterStageWindow *stage_window); gboolean (* realize) (ClutterStageWindow *stage_window);
void (* unrealize) (ClutterStageWindow *stage_window); void (* unrealize) (ClutterStageWindow *stage_window);
@@ -44,14 +46,23 @@ struct _ClutterStageWindowInterface
void (* get_geometry) (ClutterStageWindow *stage_window, void (* get_geometry) (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *geometry); cairo_rectangle_int_t *geometry);
void (* redraw_view) (ClutterStageWindow *stage_window, void (* schedule_update) (ClutterStageWindow *stage_window,
ClutterStageView *view); int sync_delay);
gint64 (* get_update_time) (ClutterStageWindow *stage_window);
void (* clear_update_time) (ClutterStageWindow *stage_window);
void (* set_accept_focus) (ClutterStageWindow *stage_window,
gboolean accept_focus);
void (* redraw) (ClutterStageWindow *stage_window);
gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window); gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window);
GList *(* get_views) (ClutterStageWindow *stage_window); GList *(* get_views) (ClutterStageWindow *stage_window);
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window); int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
void (* finish_frame) (ClutterStageWindow *stage_window); void (* finish_frame) (ClutterStageWindow *stage_window);
int64_t (* get_next_presentation_time) (ClutterStageWindow *stage_window);
}; };
ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window); ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window);
@@ -74,12 +85,15 @@ void _clutter_stage_window_resize (ClutterStageWin
CLUTTER_EXPORT CLUTTER_EXPORT
void _clutter_stage_window_get_geometry (ClutterStageWindow *window, void _clutter_stage_window_get_geometry (ClutterStageWindow *window,
cairo_rectangle_int_t *geometry); cairo_rectangle_int_t *geometry);
void _clutter_stage_window_schedule_update (ClutterStageWindow *window,
int sync_delay);
gint64 _clutter_stage_window_get_update_time (ClutterStageWindow *window);
void _clutter_stage_window_clear_update_time (ClutterStageWindow *window);
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window, void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus); gboolean accept_focus);
void _clutter_stage_window_redraw_view (ClutterStageWindow *window, void _clutter_stage_window_redraw (ClutterStageWindow *window);
ClutterStageView *view);
gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window); gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window);
@@ -89,6 +103,8 @@ void _clutter_stage_window_finish_frame (ClutterStageWin
int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window); int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window);
int64_t _clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window);
G_END_DECLS G_END_DECLS
#endif /* __CLUTTER_STAGE_WINDOW_H__ */ #endif /* __CLUTTER_STAGE_WINDOW_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -28,8 +28,8 @@
#error "Only <clutter/clutter.h> can be included directly." #error "Only <clutter/clutter.h> can be included directly."
#endif #endif
#include <clutter/clutter-actor.h>
#include <clutter/clutter-types.h> #include <clutter/clutter-types.h>
#include <clutter/clutter-group.h>
#include <clutter/clutter-stage-view.h> #include <clutter/clutter-stage-view.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@@ -56,7 +56,7 @@ typedef struct _ClutterStagePrivate ClutterStagePrivate;
struct _ClutterStage struct _ClutterStage
{ {
/*< private >*/ /*< private >*/
ClutterActor parent_instance; ClutterGroup parent_instance;
ClutterStagePrivate *priv; ClutterStagePrivate *priv;
}; };
@@ -74,7 +74,7 @@ struct _ClutterStage
struct _ClutterStageClass struct _ClutterStageClass
{ {
/*< private >*/ /*< private >*/
ClutterActorClass parent_class; ClutterGroupClass parent_class;
/*< public >*/ /*< public >*/
/* signals */ /* signals */
@@ -103,7 +103,8 @@ struct _ClutterStageClass
* @z_far: the distance from the viewer to the far clipping * @z_far: the distance from the viewer to the far clipping
* plane (always positive) * plane (always positive)
* *
* Stage perspective definition. * Stage perspective definition. #ClutterPerspective is only used by
* the fixed point version of clutter_stage_set_perspective().
* *
* Since: 0.4 * Since: 0.4
*/ */
@@ -139,10 +140,17 @@ GType clutter_stage_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterActor * clutter_stage_new (void); ClutterActor * clutter_stage_new (void);
CLUTTER_EXPORT
void clutter_stage_set_perspective (ClutterStage *stage,
ClutterPerspective *perspective);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_get_perspective (ClutterStage *stage, void clutter_stage_get_perspective (ClutterStage *stage,
ClutterPerspective *perspective); ClutterPerspective *perspective);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_show_cursor (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_hide_cursor (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_set_title (ClutterStage *stage, void clutter_stage_set_title (ClutterStage *stage,
const gchar *title); const gchar *title);
CLUTTER_EXPORT CLUTTER_EXPORT
@@ -178,6 +186,11 @@ void clutter_stage_set_motion_events_enabled (ClutterStage
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_stage_get_motion_events_enabled (ClutterStage *stage); gboolean clutter_stage_get_motion_events_enabled (ClutterStage *stage);
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_set_accept_focus (ClutterStage *stage,
gboolean accept_focus);
CLUTTER_EXPORT
gboolean clutter_stage_get_accept_focus (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_stage_event (ClutterStage *stage, gboolean clutter_stage_event (ClutterStage *stage,
ClutterEvent *event); ClutterEvent *event);
@@ -195,10 +208,11 @@ guchar * clutter_stage_read_pixels (ClutterStage
CLUTTER_EXPORT CLUTTER_EXPORT
void clutter_stage_ensure_viewport (ClutterStage *stage); void clutter_stage_ensure_viewport (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_ensure_redraw (ClutterStage *stage);
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_stage_is_redraw_queued_on_view (ClutterStage *stage, gboolean clutter_stage_is_redraw_queued (ClutterStage *stage);
ClutterStageView *view);
#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API #ifdef CLUTTER_ENABLE_EXPERIMENTAL_API
CLUTTER_EXPORT CLUTTER_EXPORT
@@ -208,9 +222,6 @@ CLUTTER_EXPORT
void clutter_stage_skip_sync_delay (ClutterStage *stage); void clutter_stage_skip_sync_delay (ClutterStage *stage);
#endif #endif
CLUTTER_EXPORT
void clutter_stage_schedule_update (ClutterStage *stage);
CLUTTER_EXPORT CLUTTER_EXPORT
gboolean clutter_stage_get_capture_final_size (ClutterStage *stage, gboolean clutter_stage_get_capture_final_size (ClutterStage *stage,
cairo_rectangle_int_t *rect, cairo_rectangle_int_t *rect,

View File

@@ -187,6 +187,9 @@ struct _ClutterTextPrivate
ClutterInputContentHintFlags input_hints; ClutterInputContentHintFlags input_hints;
ClutterInputContentPurpose input_purpose; ClutterInputContentPurpose input_purpose;
/* Signal handler for when the :resource-scale changes */
gulong resource_scale_changed_id;
/* bitfields */ /* bitfields */
guint alignment : 2; guint alignment : 2;
guint wrap : 1; guint wrap : 1;
@@ -595,7 +598,9 @@ ensure_effective_pango_scale_attribute (ClutterText *self)
float resource_scale; float resource_scale;
ClutterTextPrivate *priv = self->priv; ClutterTextPrivate *priv = self->priv;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale) ||
resource_scale == 1.0)
return;
if (priv->effective_attrs != NULL) if (priv->effective_attrs != NULL)
{ {
@@ -917,6 +922,18 @@ clutter_text_direction_changed_cb (GObject *gobject,
/* no need to queue a relayout: set_text_direction() will do that for us */ /* no need to queue a relayout: set_text_direction() will do that for us */
} }
static void
clutter_text_resource_scale_changed_cb (GObject *gobject,
GParamSpec *pspec)
{
ClutterText *self = CLUTTER_TEXT (gobject);
ClutterTextPrivate *priv = self->priv;
g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref);
clutter_text_dirty_cache (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (gobject));
}
/* /*
* clutter_text_create_layout: * clutter_text_create_layout:
* @text: a #ClutterText * @text: a #ClutterText
@@ -1120,7 +1137,8 @@ maybe_create_text_layout_with_resource_scale (ClutterText *text,
{ {
float resource_scale; float resource_scale;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (text)); if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale))
return NULL;
return create_text_layout_with_scale (text, return create_text_layout_with_scale (text,
allocation_width, allocation_width,
@@ -1152,7 +1170,8 @@ clutter_text_coords_to_position (ClutterText *self,
g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0); g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0);
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return 0;
/* Take any offset due to scrolling into account, and normalize /* Take any offset due to scrolling into account, and normalize
* the coordinates to PangoScale units * the coordinates to PangoScale units
@@ -1280,7 +1299,8 @@ clutter_text_position_to_coords (ClutterText *self,
g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE); g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE);
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return FALSE;
ret = clutter_text_position_to_coords_internal (self, position, ret = clutter_text_position_to_coords_internal (self, position,
x, y, line_height); x, y, line_height);
@@ -1756,6 +1776,7 @@ clutter_text_dispose (GObject *gobject)
clutter_text_dirty_cache (self); clutter_text_dirty_cache (self);
g_clear_signal_handler (&priv->direction_changed_id, self); g_clear_signal_handler (&priv->direction_changed_id, self);
g_clear_signal_handler (&priv->resource_scale_changed_id, self);
g_clear_signal_handler (&priv->settings_changed_id, g_clear_signal_handler (&priv->settings_changed_id,
clutter_get_default_backend ()); clutter_get_default_backend ());
@@ -1886,6 +1907,14 @@ clutter_text_foreach_selection_rectangle (ClutterText *self,
g_free (utf8); g_free (utf8);
} }
static void
add_selection_rectangle_to_path (ClutterText *text,
const ClutterActorBox *box,
gpointer user_data)
{
cogl_path_rectangle (user_data, box->x1, box->y1, box->x2, box->y2);
}
static void static void
clutter_text_foreach_selection_rectangle_prescaled (ClutterText *self, clutter_text_foreach_selection_rectangle_prescaled (ClutterText *self,
ClutterTextSelectionFunc func, ClutterTextSelectionFunc func,
@@ -1894,60 +1923,6 @@ clutter_text_foreach_selection_rectangle_prescaled (ClutterText *se
clutter_text_foreach_selection_rectangle (self, 1.0f, func, user_data); clutter_text_foreach_selection_rectangle (self, 1.0f, func, user_data);
} }
static void
paint_selection_rectangle (ClutterText *self,
const ClutterActorBox *box,
gpointer user_data)
{
CoglFramebuffer *fb = user_data;
ClutterTextPrivate *priv = self->priv;
ClutterActor *actor = CLUTTER_ACTOR (self);
guint8 paint_opacity = clutter_actor_get_paint_opacity (actor);
CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline);
PangoLayout *layout = clutter_text_get_layout (self);
CoglColor cogl_color = { 0, };
const ClutterColor *color;
/* Paint selection background */
if (priv->selection_color_set)
color = &priv->selection_color;
else if (priv->cursor_color_set)
color = &priv->cursor_color;
else
color = &priv->text_color;
cogl_color_init_from_4ub (&cogl_color,
color->red,
color->green,
color->blue,
paint_opacity * color->alpha / 255);
cogl_color_premultiply (&cogl_color);
cogl_pipeline_set_color (color_pipeline, &cogl_color);
cogl_framebuffer_push_rectangle_clip (fb,
box->x1, box->y1,
box->x2, box->y2);
cogl_framebuffer_draw_rectangle (fb, color_pipeline,
box->x1, box->y1,
box->x2, box->y2);
if (priv->selected_text_color_set)
color = &priv->selected_text_color;
else
color = &priv->text_color;
cogl_color_init_from_4ub (&cogl_color,
color->red,
color->green,
color->blue,
paint_opacity * color->alpha / 255);
cogl_pango_show_layout (fb, layout, priv->text_x, 0, &cogl_color);
cogl_framebuffer_pop_clip (fb);
cogl_object_unref (color_pipeline);
}
/* Draws the selected text, its background, and the cursor */ /* Draws the selected text, its background, and the cursor */
static void static void
selection_paint (ClutterText *self, selection_paint (ClutterText *self,
@@ -1990,9 +1965,52 @@ selection_paint (ClutterText *self,
} }
else else
{ {
/* Paint selection background first */
CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline);
PangoLayout *layout = clutter_text_get_layout (self);
CoglPath *selection_path = cogl_path_new ();
CoglColor cogl_color = { 0, };
/* Paint selection background */
if (priv->selection_color_set)
color = &priv->selection_color;
else if (priv->cursor_color_set)
color = &priv->cursor_color;
else
color = &priv->text_color;
cogl_color_init_from_4ub (&cogl_color,
color->red,
color->green,
color->blue,
paint_opacity * color->alpha / 255);
cogl_color_premultiply (&cogl_color);
cogl_pipeline_set_color (color_pipeline, &cogl_color);
clutter_text_foreach_selection_rectangle_prescaled (self, clutter_text_foreach_selection_rectangle_prescaled (self,
paint_selection_rectangle, add_selection_rectangle_to_path,
fb); selection_path);
cogl_framebuffer_fill_path (fb, color_pipeline, selection_path);
/* Paint selected text */
cogl_framebuffer_push_path_clip (fb, selection_path);
cogl_object_unref (selection_path);
if (priv->selected_text_color_set)
color = &priv->selected_text_color;
else
color = &priv->text_color;
cogl_color_init_from_4ub (&cogl_color,
color->red,
color->green,
color->blue,
paint_opacity * color->alpha / 255);
cogl_pango_show_layout (fb, layout, priv->text_x, 0, &cogl_color);
cogl_framebuffer_pop_clip (fb);
} }
} }
@@ -2620,7 +2638,8 @@ clutter_text_paint (ClutterActor *self,
!clutter_text_should_draw_cursor (text)) !clutter_text_should_draw_cursor (text))
return; return;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self)); if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return;
clutter_actor_box_scale (&alloc, resource_scale); clutter_actor_box_scale (&alloc, resource_scale);
clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height); clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height);
@@ -2852,7 +2871,8 @@ clutter_text_get_paint_volume (ClutterActor *self,
if (!clutter_actor_has_allocation (self)) if (!clutter_actor_has_allocation (self))
return FALSE; return FALSE;
resource_scale = clutter_actor_get_resource_scale (self); if (!clutter_actor_get_resource_scale (self, &resource_scale))
return FALSE;
_clutter_paint_volume_init_static (&priv->paint_volume, self); _clutter_paint_volume_init_static (&priv->paint_volume, self);
@@ -2909,7 +2929,8 @@ clutter_text_get_preferred_width (ClutterActor *self,
gfloat layout_width; gfloat layout_width;
gfloat resource_scale; gfloat resource_scale;
resource_scale = clutter_actor_get_resource_scale (self); if (!clutter_actor_get_resource_scale (self, &resource_scale))
resource_scale = 1;
layout = clutter_text_create_layout (text, -1, -1); layout = clutter_text_create_layout (text, -1, -1);
pango_layout_get_extents (layout, NULL, &logical_rect); pango_layout_get_extents (layout, NULL, &logical_rect);
@@ -2965,7 +2986,8 @@ clutter_text_get_preferred_height (ClutterActor *self,
gfloat layout_height; gfloat layout_height;
gfloat resource_scale; gfloat resource_scale;
resource_scale = clutter_actor_get_resource_scale (self); if (!clutter_actor_get_resource_scale (self, &resource_scale))
resource_scale = 1;
if (priv->single_line_mode) if (priv->single_line_mode)
for_width = -1; for_width = -1;
@@ -3012,7 +3034,8 @@ clutter_text_get_preferred_height (ClutterActor *self,
static void static void
clutter_text_allocate (ClutterActor *self, clutter_text_allocate (ClutterActor *self,
const ClutterActorBox *box) const ClutterActorBox *box,
ClutterAllocationFlags flags)
{ {
ClutterText *text = CLUTTER_TEXT (self); ClutterText *text = CLUTTER_TEXT (self);
ClutterActorClass *parent_class; ClutterActorClass *parent_class;
@@ -3032,7 +3055,7 @@ clutter_text_allocate (ClutterActor *self,
box->y2 - box->y1); box->y2 - box->y1);
parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class); parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
parent_class->allocate (self, box); parent_class->allocate (self, box, flags);
} }
static gboolean static gboolean
@@ -3041,33 +3064,6 @@ clutter_text_has_overlaps (ClutterActor *self)
return clutter_text_should_draw_cursor ((ClutterText *) self); return clutter_text_should_draw_cursor ((ClutterText *) self);
} }
static float
clutter_text_calculate_resource_scale (ClutterActor *actor,
int phase)
{
ClutterActorClass *parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
float new_resource_scale;
new_resource_scale = parent_class->calculate_resource_scale (actor, phase);
if (phase == 1)
return MAX (new_resource_scale, clutter_actor_get_real_resource_scale (actor));
return new_resource_scale;
}
static void
clutter_text_resource_scale_changed (ClutterActor *actor)
{
ClutterText *text = CLUTTER_TEXT (actor);
ClutterTextPrivate *priv = text->priv;
g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref);
clutter_text_dirty_cache (text);
clutter_actor_queue_immediate_relayout (actor);
}
static void static void
clutter_text_im_focus (ClutterText *text) clutter_text_im_focus (ClutterText *text)
{ {
@@ -3816,8 +3812,6 @@ clutter_text_class_init (ClutterTextClass *klass)
actor_class->key_focus_in = clutter_text_key_focus_in; actor_class->key_focus_in = clutter_text_key_focus_in;
actor_class->key_focus_out = clutter_text_key_focus_out; actor_class->key_focus_out = clutter_text_key_focus_out;
actor_class->has_overlaps = clutter_text_has_overlaps; actor_class->has_overlaps = clutter_text_has_overlaps;
actor_class->calculate_resource_scale = clutter_text_calculate_resource_scale;
actor_class->resource_scale_changed = clutter_text_resource_scale_changed;
/** /**
* ClutterText:buffer: * ClutterText:buffer:
@@ -4625,6 +4619,11 @@ clutter_text_init (ClutterText *self)
NULL); NULL);
priv->input_focus = clutter_text_input_focus_new (self); priv->input_focus = clutter_text_input_focus_new (self);
priv->resource_scale_changed_id =
g_signal_connect (self, "notify::resource-scale",
G_CALLBACK (clutter_text_resource_scale_changed_cb),
NULL);
} }
/** /**
@@ -4785,11 +4784,11 @@ clutter_text_queue_redraw_or_relayout (ClutterText *self)
clutter_text_get_preferred_height (actor, preferred_width, NULL, &preferred_height); clutter_text_get_preferred_height (actor, preferred_width, NULL, &preferred_height);
if (clutter_actor_has_allocation (actor) && if (clutter_actor_has_allocation (actor) &&
fabsf (preferred_width - clutter_actor_get_width (actor)) <= 0.001 && (fabsf (preferred_width - clutter_actor_get_width (actor)) > 0.001 ||
fabsf (preferred_height - clutter_actor_get_height (actor)) <= 0.001) fabsf (preferred_height - clutter_actor_get_height (actor)) > 0.001))
clutter_text_queue_redraw (actor);
else
clutter_actor_queue_relayout (actor); clutter_actor_queue_relayout (actor);
else
clutter_text_queue_redraw (actor);
} }
static void static void

View File

@@ -1,33 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
*
* Copyright (C) 2009 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_TIMELINE_PRIVATE_H
#define CLUTTER_TIMELINE_PRIVATE_H
void _clutter_timeline_advance (ClutterTimeline *timeline,
int64_t tick_time);
int64_t _clutter_timeline_get_delta (ClutterTimeline *timeline);
void _clutter_timeline_do_tick (ClutterTimeline *timeline,
int64_t tick_time);
#endif /* CLUTTER_TIMELINE_PRIVATE_H */

View File

@@ -24,6 +24,7 @@
/** /**
* SECTION:clutter-timeline * SECTION:clutter-timeline
* @short_description: A class for time-based events * @short_description: A class for time-based events
* @see_also: #ClutterAnimation, #ClutterAnimator, #ClutterState
* *
* #ClutterTimeline is a base class for managing time-based event that cause * #ClutterTimeline is a base class for managing time-based event that cause
* Clutter to redraw a stage, such as animations. * Clutter to redraw a stage, such as animations.
@@ -70,7 +71,7 @@
* when reaching completion by using the #ClutterTimeline:auto-reverse property. * when reaching completion by using the #ClutterTimeline:auto-reverse property.
* *
* Timelines are used in the Clutter animation framework by classes like * Timelines are used in the Clutter animation framework by classes like
* #ClutterTransition. * #ClutterAnimation, #ClutterAnimator, and #ClutterState.
* *
* ## Defining Timelines in ClutterScript * ## Defining Timelines in ClutterScript
* *
@@ -95,31 +96,22 @@
#include "clutter-build-config.h" #include "clutter-build-config.h"
#include "clutter-timeline.h" #include "clutter-timeline.h"
#include "deprecated/clutter-timeline.h"
#include "clutter-debug.h" #include "clutter-debug.h"
#include "clutter-easing.h" #include "clutter-easing.h"
#include "clutter-enum-types.h" #include "clutter-enum-types.h"
#include "clutter-frame-clock.h"
#include "clutter-main.h" #include "clutter-main.h"
#include "clutter-marshal.h" #include "clutter-marshal.h"
#include "clutter-master-clock.h"
#include "clutter-private.h" #include "clutter-private.h"
#include "clutter-scriptable.h" #include "clutter-scriptable.h"
#include "clutter-timeline-private.h"
#include "deprecated/clutter-timeline.h"
struct _ClutterTimelinePrivate struct _ClutterTimelinePrivate
{ {
ClutterTimelineDirection direction; ClutterTimelineDirection direction;
ClutterFrameClock *custom_frame_clock;
ClutterFrameClock *frame_clock;
ClutterActor *actor;
gulong actor_destroy_handler_id;
gulong actor_stage_views_handler_id;
gulong stage_stage_views_handler_id;
ClutterActor *stage;
guint delay_id; guint delay_id;
/* The total length in milliseconds of this timeline */ /* The total length in milliseconds of this timeline */
@@ -181,14 +173,13 @@ enum
{ {
PROP_0, PROP_0,
PROP_ACTOR, PROP_LOOP,
PROP_DELAY, PROP_DELAY,
PROP_DURATION, PROP_DURATION,
PROP_DIRECTION, PROP_DIRECTION,
PROP_AUTO_REVERSE, PROP_AUTO_REVERSE,
PROP_REPEAT_COUNT, PROP_REPEAT_COUNT,
PROP_PROGRESS_MODE, PROP_PROGRESS_MODE,
PROP_FRAME_CLOCK,
PROP_LAST PROP_LAST
}; };
@@ -209,8 +200,6 @@ enum
static guint timeline_signals[LAST_SIGNAL] = { 0, }; static guint timeline_signals[LAST_SIGNAL] = { 0, };
static void update_frame_clock (ClutterTimeline *timeline);
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT, G_DEFINE_TYPE_WITH_CODE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT,
@@ -302,175 +291,21 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline,
g_hash_table_insert (priv->markers_by_name, marker->name, marker); g_hash_table_insert (priv->markers_by_name, marker->name, marker);
} }
static void static inline void
on_actor_destroyed (ClutterActor *actor, clutter_timeline_set_loop_internal (ClutterTimeline *timeline,
ClutterTimeline *timeline) gboolean loop)
{ {
ClutterTimelinePrivate *priv = timeline->priv; gint old_repeat_count;
priv->actor = NULL; old_repeat_count = timeline->priv->repeat_count;
}
/** if (loop)
* clutter_timeline_get_actor: clutter_timeline_set_repeat_count (timeline, -1);
* @timeline: a #ClutterTimeline else
* clutter_timeline_set_repeat_count (timeline, 0);
* Get the actor the timeline is associated with.
*
* Returns: (transfer none): the associated #ClutterActor
*/
ClutterActor *
clutter_timeline_get_actor (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
return priv->actor; if (old_repeat_count != timeline->priv->repeat_count)
} g_object_notify_by_pspec (G_OBJECT (timeline), obj_props[PROP_LOOP]);
static void
maybe_add_timeline (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
if (!priv->frame_clock)
return;
clutter_frame_clock_add_timeline (priv->frame_clock, timeline);
}
static void
maybe_remove_timeline (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
if (!priv->frame_clock)
return;
clutter_frame_clock_remove_timeline (priv->frame_clock, timeline);
}
static void
set_frame_clock_internal (ClutterTimeline *timeline,
ClutterFrameClock *frame_clock)
{
ClutterTimelinePrivate *priv = timeline->priv;
if (priv->frame_clock == frame_clock)
return;
if (priv->frame_clock && priv->is_playing)
maybe_remove_timeline (timeline);
g_set_object (&priv->frame_clock, frame_clock);
g_object_notify_by_pspec (G_OBJECT (timeline),
obj_props[PROP_FRAME_CLOCK]);
if (priv->is_playing)
maybe_add_timeline (timeline);
}
static void
on_stage_stage_views_changed (ClutterActor *stage,
ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
priv->stage = NULL;
update_frame_clock (timeline);
}
static void
update_frame_clock (ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
ClutterFrameClock *frame_clock = NULL;
ClutterActor *stage;
if (!priv->actor)
goto out;
frame_clock = clutter_actor_pick_frame_clock (priv->actor);
if (frame_clock)
{
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
goto out;
}
stage = clutter_actor_get_stage (priv->actor);
if (!stage)
{
if (priv->is_playing)
g_warning ("Timelines with detached actors are not supported");
goto out;
}
if (priv->stage_stage_views_handler_id > 0)
goto out;
priv->stage_stage_views_handler_id =
g_signal_connect (stage, "stage-views-changed",
G_CALLBACK (on_stage_stage_views_changed),
timeline);
priv->stage = stage;
out:
set_frame_clock_internal (timeline, frame_clock);
}
static void
on_actor_stage_views_changed (ClutterActor *actor,
ClutterTimeline *timeline)
{
update_frame_clock (timeline);
}
/**
* clutter_timeline_set_actor:
* @timeline: a #ClutterTimeline
* @actor: (nullable): a #ClutterActor
*
* Set the actor the timeline is associated with.
*/
void
clutter_timeline_set_actor (ClutterTimeline *timeline,
ClutterActor *actor)
{
ClutterTimelinePrivate *priv = timeline->priv;
g_return_if_fail (!actor || (actor && !priv->custom_frame_clock));
if (priv->actor)
{
g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor);
g_clear_signal_handler (&priv->actor_stage_views_handler_id, priv->actor);
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
priv->stage = NULL;
priv->actor = NULL;
if (priv->is_playing)
maybe_remove_timeline (timeline);
priv->frame_clock = NULL;
}
priv->actor = actor;
if (priv->actor)
{
priv->actor_destroy_handler_id =
g_signal_connect (priv->actor, "destroy",
G_CALLBACK (on_actor_destroyed),
timeline);
priv->actor_stage_views_handler_id =
g_signal_connect (priv->actor, "stage-views-changed",
G_CALLBACK (on_actor_stage_views_changed),
timeline);
}
update_frame_clock (timeline);
} }
/* Scriptable */ /* Scriptable */
@@ -614,8 +449,8 @@ clutter_timeline_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_ACTOR: case PROP_LOOP:
clutter_timeline_set_actor (timeline, g_value_get_object (value)); clutter_timeline_set_loop_internal (timeline, g_value_get_boolean (value));
break; break;
case PROP_DELAY: case PROP_DELAY:
@@ -642,10 +477,6 @@ clutter_timeline_set_property (GObject *object,
clutter_timeline_set_progress_mode (timeline, g_value_get_enum (value)); clutter_timeline_set_progress_mode (timeline, g_value_get_enum (value));
break; break;
case PROP_FRAME_CLOCK:
clutter_timeline_set_frame_clock (timeline, g_value_get_object (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -663,8 +494,8 @@ clutter_timeline_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_ACTOR: case PROP_LOOP:
g_value_set_object (value, priv->actor); g_value_set_boolean (value, priv->repeat_count != 0);
break; break;
case PROP_DELAY: case PROP_DELAY:
@@ -691,10 +522,6 @@ clutter_timeline_get_property (GObject *object,
g_value_set_enum (value, priv->progress_mode); g_value_set_enum (value, priv->progress_mode);
break; break;
case PROP_FRAME_CLOCK:
g_value_set_object (value, priv->frame_clock);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -706,14 +533,16 @@ clutter_timeline_finalize (GObject *object)
{ {
ClutterTimeline *self = CLUTTER_TIMELINE (object); ClutterTimeline *self = CLUTTER_TIMELINE (object);
ClutterTimelinePrivate *priv = self->priv; ClutterTimelinePrivate *priv = self->priv;
ClutterMasterClock *master_clock;
if (priv->markers_by_name) if (priv->markers_by_name)
g_hash_table_destroy (priv->markers_by_name); g_hash_table_destroy (priv->markers_by_name);
if (priv->is_playing) if (priv->is_playing)
maybe_remove_timeline (self); {
master_clock = _clutter_master_clock_get_default ();
g_clear_object (&priv->frame_clock); _clutter_master_clock_remove_timeline (master_clock, self);
}
G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object); G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object);
} }
@@ -728,14 +557,6 @@ clutter_timeline_dispose (GObject *object)
clutter_timeline_cancel_delay (self); clutter_timeline_cancel_delay (self);
if (priv->actor)
{
g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor);
g_clear_signal_handler (&priv->actor_stage_views_handler_id, priv->actor);
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
priv->actor = NULL;
}
if (priv->progress_notify != NULL) if (priv->progress_notify != NULL)
{ {
priv->progress_notify (priv->progress_data); priv->progress_notify (priv->progress_data);
@@ -753,17 +574,24 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
/** /**
* ClutterTimeline::actor: * ClutterTimeline:loop:
* *
* The actor the timeline is associated with. This will determine what frame * Whether the timeline should automatically rewind and restart.
* clock will drive it. *
* As a side effect, setting this property to %TRUE will set the
* #ClutterTimeline:repeat-count property to -1, while setting this
* property to %FALSE will set the #ClutterTimeline:repeat-count
* property to 0.
*
* Deprecated: 1.10: Use the #ClutterTimeline:repeat-count property instead.
*/ */
obj_props[PROP_ACTOR] = obj_props[PROP_LOOP] =
g_param_spec_object ("actor", g_param_spec_boolean ("loop",
P_("Actor"), P_("Loop"),
P_("Associated ClutterActor"), P_("Should the timeline automatically restart"),
CLUTTER_TYPE_ACTOR, FALSE,
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE); CLUTTER_PARAM_READWRITE | G_PARAM_DEPRECATED);
/** /**
* ClutterTimeline:delay: * ClutterTimeline:delay:
* *
@@ -862,18 +690,6 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
CLUTTER_LINEAR, CLUTTER_LINEAR,
CLUTTER_PARAM_READWRITE); CLUTTER_PARAM_READWRITE);
/**
* ClutterTimeline:frame-clock:
*
* The frame clock driving the timeline.
*/
obj_props[PROP_FRAME_CLOCK] =
g_param_spec_object ("frame-clock",
"Frame clock",
"Frame clock driving the timeline",
CLUTTER_TYPE_FRAME_CLOCK,
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
object_class->dispose = clutter_timeline_dispose; object_class->dispose = clutter_timeline_dispose;
object_class->finalize = clutter_timeline_finalize; object_class->finalize = clutter_timeline_finalize;
object_class->set_property = clutter_timeline_set_property; object_class->set_property = clutter_timeline_set_property;
@@ -1156,6 +972,7 @@ set_is_playing (ClutterTimeline *timeline,
gboolean is_playing) gboolean is_playing)
{ {
ClutterTimelinePrivate *priv = timeline->priv; ClutterTimelinePrivate *priv = timeline->priv;
ClutterMasterClock *master_clock;
is_playing = !!is_playing; is_playing = !!is_playing;
@@ -1164,17 +981,15 @@ set_is_playing (ClutterTimeline *timeline,
priv->is_playing = is_playing; priv->is_playing = is_playing;
master_clock = _clutter_master_clock_get_default ();
if (priv->is_playing) if (priv->is_playing)
{ {
priv->waiting_first_tick = TRUE; priv->waiting_first_tick = TRUE;
priv->current_repeat = 0; priv->current_repeat = 0;
_clutter_master_clock_add_timeline (master_clock, timeline);
maybe_add_timeline (timeline);
} }
else else
{ _clutter_master_clock_remove_timeline (master_clock, timeline);
maybe_remove_timeline (timeline);
}
} }
static gboolean static gboolean
@@ -1371,9 +1186,6 @@ clutter_timeline_start (ClutterTimeline *timeline)
if (priv->duration == 0) if (priv->duration == 0)
return; return;
g_warn_if_fail ((priv->actor && clutter_actor_get_stage (priv->actor)) ||
priv->frame_clock);
if (priv->delay) if (priv->delay)
priv->delay_id = clutter_threads_add_timeout (priv->delay, priv->delay_id = clutter_threads_add_timeout (priv->delay,
delay_timeout_func, delay_timeout_func,
@@ -1440,6 +1252,45 @@ clutter_timeline_stop (ClutterTimeline *timeline)
g_signal_emit (timeline, timeline_signals[STOPPED], 0, FALSE); g_signal_emit (timeline, timeline_signals[STOPPED], 0, FALSE);
} }
/**
* clutter_timeline_set_loop:
* @timeline: a #ClutterTimeline
* @loop: %TRUE for enable looping
*
* Sets whether @timeline should loop.
*
* This function is equivalent to calling clutter_timeline_set_repeat_count()
* with -1 if @loop is %TRUE, and with 0 if @loop is %FALSE.
*
* Deprecated: 1.10: Use clutter_timeline_set_repeat_count() instead.
*/
void
clutter_timeline_set_loop (ClutterTimeline *timeline,
gboolean loop)
{
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
clutter_timeline_set_loop_internal (timeline, loop);
}
/**
* clutter_timeline_get_loop:
* @timeline: a #ClutterTimeline
*
* Gets whether @timeline is looping
*
* Return value: %TRUE if the timeline is looping
*
* Deprecated: 1.10: Use clutter_timeline_get_repeat_count() instead.
*/
gboolean
clutter_timeline_get_loop (ClutterTimeline *timeline)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), FALSE);
return timeline->priv->repeat_count != 0;
}
/** /**
* clutter_timeline_rewind: * clutter_timeline_rewind:
* @timeline: A #ClutterTimeline * @timeline: A #ClutterTimeline
@@ -1556,10 +1407,48 @@ clutter_timeline_is_playing (ClutterTimeline *timeline)
} }
/** /**
* clutter_timeline_new: * clutter_timeline_clone:
* @duration_ms: Duration of the timeline in milliseconds * @timeline: #ClutterTimeline to duplicate.
* *
* Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds. * Create a new #ClutterTimeline instance which has property values
* matching that of supplied timeline. The cloned timeline will not
* be started and will not be positioned to the current position of
* the original @timeline: you will have to start it with
* clutter_timeline_start().
*
* The only cloned properties are:
*
* - #ClutterTimeline:duration
* - #ClutterTimeline:loop
* - #ClutterTimeline:delay
* - #ClutterTimeline:direction
*
* Return value: (transfer full): a new #ClutterTimeline, cloned
* from @timeline
*
* Since: 0.4
*
* Deprecated: 1.10: Use clutter_timeline_new() or g_object_new()
* instead
*/
ClutterTimeline *
clutter_timeline_clone (ClutterTimeline *timeline)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL);
return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", timeline->priv->duration,
"loop", timeline->priv->repeat_count != 0,
"delay", timeline->priv->delay,
"direction", timeline->priv->direction,
NULL);
}
/**
* clutter_timeline_new:
* @msecs: Duration of the timeline in milliseconds
*
* Creates a new #ClutterTimeline with a duration of @msecs.
* *
* Return value: the newly created #ClutterTimeline instance. Use * Return value: the newly created #ClutterTimeline instance. Use
* g_object_unref() when done using it * g_object_unref() when done using it
@@ -1567,50 +1456,10 @@ clutter_timeline_is_playing (ClutterTimeline *timeline)
* Since: 0.6 * Since: 0.6
*/ */
ClutterTimeline * ClutterTimeline *
clutter_timeline_new (guint duration_ms) clutter_timeline_new (guint msecs)
{ {
return g_object_new (CLUTTER_TYPE_TIMELINE, return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", duration_ms, "duration", msecs,
NULL);
}
/**
* clutter_timeline_new_for_actor:
* @actor: The #ClutterActor the timeline is associated with
* @duration_ms: Duration of the timeline in milliseconds
*
* Creates a new #ClutterTimeline with a duration of @duration milli seconds.
*
* Return value: the newly created #ClutterTimeline instance. Use
* g_object_unref() when done using it
*/
ClutterTimeline *
clutter_timeline_new_for_actor (ClutterActor *actor,
unsigned int duration_ms)
{
return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", duration_ms,
"actor", actor,
NULL);
}
/**
* clutter_timeline_new_for_frame_clock:
* @frame_clock: The #ClutterFrameClock the timeline is driven by
* @duration_ms: Duration of the timeline in milliseconds
*
* Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds.
*
* Return value: the newly created #ClutterTimeline instance. Use
* g_object_unref() when done using it
*/
ClutterTimeline *
clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock,
unsigned int duration_ms)
{
return g_object_new (CLUTTER_TYPE_TIMELINE,
"duration", duration_ms,
"frame-clock", frame_clock,
NULL); NULL);
} }
@@ -1876,7 +1725,7 @@ _clutter_timeline_do_tick (ClutterTimeline *timeline,
/* Check the is_playing variable before performing the timeline tick. /* Check the is_playing variable before performing the timeline tick.
* This is necessary, as if a timeline is stopped in response to a * This is necessary, as if a timeline is stopped in response to a
* frame clock generated signal of a different timeline, this code can * master-clock generated signal of a different timeline, this code can
* still be reached. * still be reached.
*/ */
if (!priv->is_playing) if (!priv->is_playing)
@@ -2694,32 +2543,3 @@ clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
return TRUE; return TRUE;
} }
/**
* clutter_timeline_get_frame_clock: (skip)
*/
ClutterFrameClock *
clutter_timeline_get_frame_clock (ClutterTimeline *timeline)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL);
return timeline->priv->frame_clock;
}
void
clutter_timeline_set_frame_clock (ClutterTimeline *timeline,
ClutterFrameClock *frame_clock)
{
ClutterTimelinePrivate *priv;
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
priv = timeline->priv;
g_assert (!frame_clock || (frame_clock && !priv->actor));
g_return_if_fail (!frame_clock || (frame_clock && !priv->actor));
priv->custom_frame_clock = frame_clock;
if (!priv->actor)
set_frame_clock_internal (timeline, frame_clock);
}

View File

@@ -119,19 +119,7 @@ CLUTTER_EXPORT
GType clutter_timeline_get_type (void) G_GNUC_CONST; GType clutter_timeline_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new_for_actor (ClutterActor *actor, ClutterTimeline * clutter_timeline_new (guint msecs);
unsigned int duration_ms);
CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock,
unsigned int duration_ms);
CLUTTER_EXPORT
ClutterActor * clutter_timeline_get_actor (ClutterTimeline *timeline);
CLUTTER_EXPORT
void clutter_timeline_set_actor (ClutterTimeline *timeline,
ClutterActor *actor);
CLUTTER_EXPORT CLUTTER_EXPORT
guint clutter_timeline_get_duration (ClutterTimeline *timeline); guint clutter_timeline_get_duration (ClutterTimeline *timeline);
@@ -233,13 +221,6 @@ gint64 clutter_timeline_get_duration_hint
CLUTTER_EXPORT CLUTTER_EXPORT
gint clutter_timeline_get_current_repeat (ClutterTimeline *timeline); gint clutter_timeline_get_current_repeat (ClutterTimeline *timeline);
CLUTTER_EXPORT
ClutterFrameClock * clutter_timeline_get_frame_clock (ClutterTimeline *timeline);
CLUTTER_EXPORT
void clutter_timeline_set_frame_clock (ClutterTimeline *timeline,
ClutterFrameClock *frame_clock);
G_END_DECLS G_END_DECLS
#endif /* _CLUTTER_TIMELINE_H__ */ #endif /* _CLUTTER_TIMELINE_H__ */

View File

@@ -43,7 +43,6 @@
#include "clutter-debug.h" #include "clutter-debug.h"
#include "clutter-private.h" #include "clutter-private.h"
#include "clutter-timeline-private.h"
struct _ClutterTransitionGroupPrivate struct _ClutterTransitionGroupPrivate
{ {

View File

@@ -364,7 +364,6 @@ clutter_transition_set_animatable (ClutterTransition *transition,
ClutterAnimatable *animatable) ClutterAnimatable *animatable)
{ {
ClutterTransitionPrivate *priv; ClutterTransitionPrivate *priv;
ClutterActor *actor;
g_return_if_fail (CLUTTER_IS_TRANSITION (transition)); g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
g_return_if_fail (animatable == NULL || CLUTTER_IS_ANIMATABLE (animatable)); g_return_if_fail (animatable == NULL || CLUTTER_IS_ANIMATABLE (animatable));
@@ -384,9 +383,6 @@ clutter_transition_set_animatable (ClutterTransition *transition,
priv->animatable = g_object_ref (animatable); priv->animatable = g_object_ref (animatable);
clutter_transition_attach (transition, priv->animatable); clutter_transition_attach (transition, priv->animatable);
} }
actor = clutter_animatable_get_actor (animatable);
clutter_timeline_set_actor (CLUTTER_TIMELINE (transition), actor);
} }
/** /**

View File

@@ -57,7 +57,6 @@ typedef struct _ClutterActorIter ClutterActorIter;
typedef struct _ClutterPaintNode ClutterPaintNode; typedef struct _ClutterPaintNode ClutterPaintNode;
typedef struct _ClutterContent ClutterContent; /* dummy */ typedef struct _ClutterContent ClutterContent; /* dummy */
typedef struct _ClutterScrollActor ClutterScrollActor; typedef struct _ClutterScrollActor ClutterScrollActor;
typedef struct _ClutterFrameClock ClutterFrameClock;
typedef struct _ClutterInterval ClutterInterval; typedef struct _ClutterInterval ClutterInterval;
typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */ typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */
@@ -80,6 +79,10 @@ typedef struct _ClutterKnot ClutterKnot;
typedef struct _ClutterMargin ClutterMargin; typedef struct _ClutterMargin ClutterMargin;
typedef struct _ClutterPerspective ClutterPerspective; typedef struct _ClutterPerspective ClutterPerspective;
typedef struct _ClutterAlpha ClutterAlpha;
typedef struct _ClutterAnimation ClutterAnimation;
typedef struct _ClutterState ClutterState;
typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool; typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool;
typedef struct _ClutterInputDevice ClutterInputDevice; typedef struct _ClutterInputDevice ClutterInputDevice;
typedef struct _ClutterVirtualInputDevice ClutterVirtualInputDevice; typedef struct _ClutterVirtualInputDevice ClutterVirtualInputDevice;
@@ -175,20 +178,6 @@ struct _ClutterActorBox
*/ */
#define CLUTTER_ACTOR_BOX_INIT_ZERO CLUTTER_ACTOR_BOX_INIT (0.f, 0.f, 0.f, 0.f) #define CLUTTER_ACTOR_BOX_INIT_ZERO CLUTTER_ACTOR_BOX_INIT (0.f, 0.f, 0.f, 0.f)
/**
* CLUTTER_ACTOR_BOX_UNINITIALIZED:
*
* A simple macro for creating a #ClutterActorBox with a size of -1 when
* declaring it, e.g.:
*
* |[
* ClutterActorBox box = CLUTTER_ACTOR_BOX_UNINITIALIZED;
* ]|
*/
#define CLUTTER_ACTOR_BOX_UNINITIALIZED { .x1 = INFINITY, .y1 = INFINITY, .x2 = -INFINITY, .y2 = -INFINITY }
CLUTTER_EXPORT CLUTTER_EXPORT
GType clutter_actor_box_get_type (void) G_GNUC_CONST; GType clutter_actor_box_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT CLUTTER_EXPORT
@@ -267,9 +256,6 @@ CLUTTER_EXPORT
void clutter_actor_box_scale (ClutterActorBox *box, void clutter_actor_box_scale (ClutterActorBox *box,
gfloat scale); gfloat scale);
CLUTTER_EXPORT
gboolean clutter_actor_box_is_initialized (ClutterActorBox *box);
/** /**
* ClutterKnot: * ClutterKnot:
* @x: X coordinate of the knot * @x: X coordinate of the knot

View File

@@ -56,6 +56,8 @@
#include "clutter-content.h" #include "clutter-content.h"
#include "clutter-deform-effect.h" #include "clutter-deform-effect.h"
#include "clutter-desaturate-effect.h" #include "clutter-desaturate-effect.h"
#include "clutter-drag-action.h"
#include "clutter-drop-action.h"
#include "clutter-effect.h" #include "clutter-effect.h"
#include "clutter-enums.h" #include "clutter-enums.h"
#include "clutter-enum-types.h" #include "clutter-enum-types.h"
@@ -63,9 +65,9 @@
#include "clutter-feature.h" #include "clutter-feature.h"
#include "clutter-fixed-layout.h" #include "clutter-fixed-layout.h"
#include "clutter-flow-layout.h" #include "clutter-flow-layout.h"
#include "clutter-frame-clock.h"
#include "clutter-gesture-action.h" #include "clutter-gesture-action.h"
#include "clutter-grid-layout.h" #include "clutter-grid-layout.h"
#include "clutter-group.h"
#include "clutter-image.h" #include "clutter-image.h"
#include "clutter-input-device.h" #include "clutter-input-device.h"
#include "clutter-input-device-tool.h" #include "clutter-input-device-tool.h"

File diff suppressed because it is too large Load Diff

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