Compare commits

...

131 Commits

Author SHA1 Message Date
Alexander Mikhaylenko
0c03702168 window: Appear as focused while focusing
Prevent focused window from blinking after switching to another
workspace on X11.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/850
2020-07-07 20:49:55 +00:00
Alexander Mikhaylenko
03514bb31a window: Make default focus window on each workspace appear focused
Makes workspace transitions in gnome-shell look more seamless, since
both outgoing and incoming workspace have focused windows.

This is only done for click focus mode, since it's not known which
window would be focused for the other modes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/850
2020-07-07 20:49:55 +00:00
Alexander Mikhaylenko
697b84e80e workspace: Add meta_workspace_get_default_focus_window()
This will be used in the next commit to make this window appear focused.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/850
2020-07-07 20:49:54 +00:00
Alexander Mikhaylenko
5fd90e85ed stack: Check workspace in get_default_focus_window()
Check against the window argument, instead of active workspace.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/850
2020-07-07 20:49:54 +00:00
Florian Müllner
30d9d1968c Bump version to 3.37.3
Update NEWS.
2020-07-07 19:24:32 +02:00
Florian Müllner
65aa476414 tests/stage-view: Keep old stage views alive on hotplug
Otherwise we cannot reliably compare them to the new post-hotplug
views.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1357
2020-07-07 17:07:20 +00:00
Jonas Dreßler
03d177cf64 clutter/actor: Add position argument to allocate_preferred_size()
Make clutter_actor_allocate_preferred_size() convenient to use from
layout managers by not "automatically" honouring the fixed position of
the actor, but instead allowing to pass a position to allocate the
actor at.

This way we can move the handling of fixed positions to
ClutterFixedLayout, the layout manager which is responsible for
allocating actors using fixed positions.

This also makes clutter_actor_allocate_preferred_size() more similar to
clutter_actor_allocate_available_size().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1310
2020-07-07 16:47:00 +00:00
Jonas Dreßler
dfa235aa5d clutter/actor: Add API to get fixed position
It's currently a bit hard to get the fixed position of an actor. It can
be either done by using g_object_get() with the "fixed-x"/"fixed-y"
properties or by calling clutter_actor_get_position().

Calling clutter_actor_get_position() can return the fixed position, but
it might also return the allocated position if the allocation is valid.
The latter is not the best behavior when querying the fixed position
during an allocation, so introduce a new function
clutter_actor_get_fixed_position() which always gets the fixed position
and returns FALSE in case no fixed position is set.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1310
2020-07-07 16:47:00 +00:00
Robert Mader
d722e59aac window-actor/wayland: Remove custom get_paint_volume() vfunc
It doesn't take all children - subsurfaces in this case - into
account, thus creating glitches if subsurfaces extend outside
of the toplevel surface.

Further more it doesn't seem to serve any special purpose - it was
added in f7315c9a36, a pretty big commit, and no discussion was
started about the code in question. So it was likely just overlooked
in the review process.

Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/873
Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/1316
2020-07-07 12:25:43 +00:00
Daniel van Vugt
32dbcd9352 background-content: Mipmap background texture rendering
gnome-shell displays workspace previews at one tenth scale. That's a
few binary orders of magnitude so even using a LINEAR filter was
resulting in visible jaggies. Now we apply mipmapping so they appear
smooth.

As an added bonus, the mipmaps used occupy roughly 1% the memory of
the original image (0.1 x 0.1 = 0.01) so they actually fit into GPU/CPU
caches now and rendering performance is improved. There's no need to
traverse the original texture which at 4K resolution occupies 33MB,
only a 331KB mipmap.

In my case this reduces the render time for the overview by ~10%.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1416

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1347
2020-07-07 16:15:28 +08:00
Daniel van Vugt
3a474556b8 cogl-texture-2d: Flush the journal before mipmapping
In the case of indirect rendering like the first frame to use mutter's
background wallpaper:

  Texture_A -> FBO_B (Texture_B) -> FBO_C (screen)

we would be trying to render the contents of both FBO_B and FBO_C in
the same flush, before the contents of Texture_A had made it to FBO_B.
So when FBO_C wants to use mipmaps of Texture_B they didn't exist yet
and appeared all black. And the blackness would remain for subsequent
frames as cogl has now decided the mipmaps of FBO_B are no longer
"dirty" and don't need refreshing:

  FBO_B (Texture_B) (mipmaps_dirty==FALSE but black) -> FBO_C (screen)

We must flush FBO_B before referencing Texture_B for use in rendering
FBO_C. This only happens when Texture_A changes (e.g. when the user
changes their background wallpaper) so there's no ongoing performance
penalty from this flush.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1347
2020-07-07 16:15:24 +08:00
Jonas Dreßler
249274c677 clutter/actor: Pass stage as user_data when unrealizing
We can avoid having to get the stage again for every child of the
subtree we're unrealizing by getting the stage once and passing it as
user_data to the callbacks.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1356
2020-07-06 19:51:35 +00:00
Jonas Dreßler
ae83a61e67 clutter/actor: Remove actors from shallow relayout list when unrealizing
With the introduction of the shallow relayout mechanism another small
but severe regression sneaked into our layout machinery: We might
allocate an actor twice during the same allocation cycle, with one
allocation happening using the wrong parent.

This issue happens when reparenting an actor from a NO_LAYOUT parent to
a non-NO_LAYOUT parent, in particular it triggered a bug in gnome-shell
when DND reparents a child from the NO_LAYOUT uiGroup to the overviews
Workspace actor after a drag ended. The reason the issue happens is the
following chain of events:

1. child of a NO_LAYOUT parent queues a relayout, this child is added to
the priv->pending_relayouts list maintained by ClutterStage

2. child is reparented to a different parent which doesn't have the
NO_LAYOUT flag set, another relayout is queued, this time a different
actor is added to the priv->pending_relayouts list

3. the relayout happens and we go through the pending_relayouts list
backwards, that means the correct relayout queued during 2. happens
first, then the old one happens and we simply call
clutter_actor_allocate_preferred_size() on the actor, that allocation
overrides the other, correct one.

So fix that issue by adding a method to ClutterStage which removes
actors from the pending_relayouts list again and call this method as
soon as an actor with a NO_LAYOUT parent is detached from the stage.

With that in place, we can also remove the check whether an actor is
still on stage while looping through pending_relayouts. In case
something else is going wrong and the actor is not on stage,
clutter_actor_allocate() will warn anyway.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1356
2020-07-06 19:51:35 +00:00
Andre Klapper
826573ccce Fix broken markup in Hausa UI translation 2020-07-06 19:32:08 +02:00
Daniel van Vugt
dbff32ec5c clutter-backend: Default to scale 1
So we at least don't trigger assertions for invalid scales of zero.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2957

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1349
2020-07-03 19:57:30 +00:00
Carlos Garnacho
2f1f47d257 x11: Look up reason for selection clear events from XFixes
If the event originates from a XSetSelectionOwner request, the event
will contain a XFixesSetSelectionOwnerNotify subtype. The other
subtypes (meant for the selection window being destroyed, and the
client closing) are the situations where we mean to replace the
selection.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1268

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1350
2020-07-03 13:58:25 +02:00
Jonas Ådahl
06781985e4 clutter/timeline: Warn if started with a detached actor
The timeline can't find a frame clock if the actor is detached, so warn
if that happens.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 20:13:53 +02:00
Georges Basile Stavracas Neto
5b0a7b3a33 clutter/timeline: Wait for stage if no frame clock is available
When picking which frame clock to use, we traverse up in the actor
hierarchy until a suitable frame clock is found. ClutterTimeline
also listens to the 'stage-views-changed' to make sure it's always
attached to the correct frame clock.

However, there is one special situation where neither of them would
work: when the stage doesn't have a frame clock yet, and the actor
of the timeline is outside any stage view. When that happens, the
returned frame clock is NULL, and 'stage-views-changed' is never
emitted by the actor.

Monitor the stage for stage view changes when the frame clock is
NULL.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
1ecdaa646f wayland: Respond to frame callbacks also if a clone was painted
This will mean that a surface on one monitor, with e.g. a preview on
another, will still get frame callbacks if the preview is painted, but
itself being hidden.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
2f4d50c723 clutter/actor: Add API to check whether actor or clone is on view
The new function returns TRUE if an actor is effectively on the passed
view, where effectively refers to itself or a clone containing itself.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
4b8bb4608c clutter/transition: Get timeline actor from animatable
Undeprecate the non-actor carrying transition constructor, and instead
rely on set_animatable() to give us a source for an actor to derive a
view and frame clock from.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
aa34f6ad7c clutter/actor: Pick frame clock of parent if not on any views
An actor may be placed without being on any current stage view; in this
case, to get the ball rolling, walk up the actor tree to find the first
actor where a frame clock can be picked from.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
f9be670522 tests/frame-clock: Check that destroy signal is emitted
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
d77bcb9028 clutter/animatable: Add way to get an actor from an animatable
This will be used by ClutterTransition to associate the timeline with an
actor, which itself will be used to determine what frame clock should
drive the timeline.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
d29c8e290c clutter/frame-clock: Add explicit destroy function
The frame clock owner should be able to explicitly destroy (i.e. make
defunct) a frame clock, e.g. when a stage view is destructed. This is so
that other objects can keep reference to its without it being left
around even after stopped being usable.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
e12ce70385 tests/stage-view: Test that timelime adapts to actor moving across views
The timeline should switch frame clock, and automatically continue on
the new frame clock.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
442f34b4de tests/stage-view: Test that actors pick the right frame clock
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
20becd782f clutter/stage-view: Export refresh rate getter symbol
To be used by tests.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
feb8bfa0bf clutter/frame-clock: Add refresh rate getter
This gets the refresh rate of the frame clock. To be used by tests.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
59a38fcb69 tests/stage-view: Check that hotplugging reestablishes view list
Currently there is a point in between hot plug, and when the stage view
list is up to date. The check also tests for this behaviour; would this
ever change, the test should be adapted to deal with this too.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
190e285c23 tests/stage-view: Remove unnecessary warning supression
It doesn't occur anymore, so lets stop ignoring it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
a9a9a0d1c5 clutter: Paint views with individual frame clocks
Replace the default master clock with multiple frame clocks, each
driving its own stage view. As each stage view represents one CRTC, this
means we draw each CRTC with its own designated frame clock,
disconnected from all the others.

For example this means we when using the native backend will never need
to wait for one monitor to vsync before painting another, so e.g. having
a 144 Hz monitor next to a 60 Hz monitor, things including both Wayland
and X11 applications and shell UI will be able to render at the
corresponding monitor refresh rate.

This also changes a warning about missed frames when sending
_NETWM_FRAME_TIMINGS messages to a debug log entry, as it's expected
that we'll start missing frames e.g. when a X11 window (via Xwayland) is
exclusively within a stage view that was not painted, while another one
was, still increasing the global frame clock.

Addititonally, this also requires the X11 window actor to schedule
timeouts for _NET_WM_FRAME_DRAWN/_NET_WM_FRAME_TIMINGS event emitting,
if the actor wasn't on any stage views, as now we'll only get the frame
callbacks on actors when they actually were painted, while in the past,
we'd invoke that vfunc when anything was painted.

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

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
57a2f7b4a3 renderer: Use 'add_view()' when adding CRTC views
This also changes the view construction path used by the renderer view
to use the new 'add_view()' function, meaning we have a common entry
point for views into the renderer, which will be useful later on.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
1f895719b3 renderer-x11-cm: Initialize screen stage view in one step
Before we'd create the view in init(), then continue poking at it in
realize(). Move all of the screen stage view initialization to
realize(), as that's when we have all the dependent state available.
This is possible since there is nothing needing it until realizing.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
37326e4a32 compositor: Use stage signals instead of clutter repaint callbacks
The repaint callbacks are not tied to repaint, thus a bit misleading.
What the functionality in the pre/post-paint callbacks here cares about
is when actually painting; the non-painting related parts has already
moved out to a *-update signal.

This also renames the related MetaWindowActorClass vfuncs, to align with
naming convention of the signals that it listens to.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
8cff3b84f7 wayland/compositor: Process frame callbacks on 'after-update'
Instead of going via MetaCompositor to know about when we updated
(confusingly named post-paint), use the new stage signal directly.

Note that this doesn't change the time frame callbacks are dispatched;
it's still not tied to actual painting even though it seemed so before
given the function names.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
578c30792a compositor: Remove unused stage pointer
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
9daec23033 cursor-renderer: Use 'after-paint' stage signal instead paint callback
The clutter "thread" repaint callback are not tied to painting, but
indirectly to updating. What the cursor renderer cares about is when we
actually painted, as this is related to the OpenGL fallback paths.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
5f729ea437 clutter/stage: Only emit "presented" on completion event
We'd emit multiple "presented" signals per frame, one for "sync" and one
for "completion". Only the latter were ever used, and removing the
differentiation eases the avoidance of cogl onscreen framebuffer frame
callback details leaking into clutter.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
ae7cc0417f compositor: Remove 'pre-paint' signal
It's not used; just use the vfunc directly.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
468bf81307 surface-actor: Remove 'pre-paint' vfunc
The vfunc was not tied to "paint", but was used by MetaWindowActorX11
as part of the "update" mechanisms. In order to make that more clear,
special case it in MetaWindowActorX11 by type checking the surface
actor, handling the case without MetaSurfacActor abstraction.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
551101c65c compositor-x11: Move synchronization to before-update
The synchronization must happen no matter the painting, as it in itself
might result in reported damage, making the stage actually painted. Thus
move it out of the "pre-paint" handler, to something explicitly not tied
to the painting itself - ClutterStage::before-update.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
110ed7ff8a laters: Use 'before-update' signal from stage
Instead of the 'pre-paint' signal on MetaCompositor, rely directly on
the 'before-update' signal on the stage. A reason for this is that the
callback should not only invoked in connection to painting, but updating
in general. Currently the 'pre-paint' signal is emitted no matter
whether there were any painting or not, but that's both misleading and
will go away.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
2afe3e9223 clutter/stage: Add signals for different update stages
Right now the stage only had a signal called 'after-paint' which was not
tied to painting but updating. Change this to offer 4 signals, for the 4
different stages:

 * before-update - emitted in the beginning before the actual stage
   updating

 * before-paint - emitted before painting if there will be any stage
   painting

 * after-paint - emitted after painting if there was any stage painting

 * after-update - emitted as a last step of updating, no matter whether
   there were any painting or not

Currently there were only one listener, that should only really have
been called if there was any painting, so no changes to listeners are
needed.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
de99dd7eb6 clutter: Remove multi thread mutexes
The mutexes was used by ClutterTexture's async upload and to match GDK's
mutexes on X11. GDK's X11 connection does not share anything with
Clutter's, we don't have the Gdk Clutter backend left, and we have
already removed ClutterTexture, so lets remove these mutexes as well.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
34be97d855 clutter/stage-view: Expose frame clock getter
So that it can be used by e.g. mutter.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
1de436684c clutter: Include clutter-frame-clock.h from clutter.h
So that it can be used by libmutter and gnome-shell.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
847e89d31f clutter/frame-clock: Handle reschedule then dispatch results in idle
A frame clock dispatch doesn't necessarily result in a frame drawn,
meaning we'll end up in the idle state. However, it may be the case that
something still requires another frame, and will in that case have
requested one to be scheduled. In order to not dead lock, try to
reschedule directly if requested after dispatching, if we ended up in
the idle state.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
f9eb140e62 clutter/actor: Add API to pick frame clock
The frame clock wouldn't be useable yet, but none the less, add API to
get the frame clock best suited for driving the actor. Currently this
translates to the fastest one, but that might change.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
3aff755048 clutte/stage-view: Add refresh rate getter
Will be used to find the view with the most appropriate refresh rate
(e.g. the fastest).

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
2e358f3c43 clutter/stage-view: Have each stage view create its own frame clock
The frame clock is meant to eventually drive the painting of the view,
in contrast to the master frame clock painting every view on the stage.
Right now it's a useless place holder.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:51 +02:00
Jonas Ådahl
c00a8e98a3 clutter/cogl: Take over global frame count responsibility
The native backend had a plain counter, and the X11 backend used the
CoglOnscreen of the screen; change it into a plain counter in
ClutterStageCogl. This also moves the global frame count setting to the
frame info constuctor.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
2a6e8bda8d cogl/onscreen: Let swap buffer caller create frame info
We currently have mutter set a global frame counter on the frame info in
the native backend, but in order to do this from clutter, change the
frame info construction from being implicitly done so when swapping
buffers to having the caller create the frame info and passing that to
the swap buffers call.

While this commit doesn't introduce any other changes than the API, the
intention is later to have the caller be able to pass it's own state
(e.g. the global frame count) along with the frame info.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
31a3b1b4c5 clutter: Include semi private cogl API
Used by mutter, but we'll need it in clutter too. This commit is to
silence type warnings that were otherwise avoided by disabling compile
time type checking.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
ff65c95aee frame-clock: Pass frame info when notifying presented
Instead of just the timestamp, pass the frame info struct we already,
that also include refresh rate.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
f086eafe57 Gather all time unit conversion helpers in one place
We had time unit conversion helpers (e.g. us2ms(), ns2us(), etc) in
multiple places. Clean that up by moving them all to a common file. That
file is clutter-private.h, as it's accessible by both from clutter/ and
src/.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
bb73038a27 clutter/stage-view: Give a stage view a refresh rate
Currently unused, but it's intention is to use as a initial refresh rate
for a with the stage view associated frame clock. It defaults to 60 Hz
if nothing sets it, but the native backend sets it to the associated
CRTCs current mode's refresh rate.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
2b95ec40c6 clutter/timeline: Deprecate timelines without an actor or frame clock
Without an associated actor, or explicit frame clock set, in the future
a timeline will not know how to progress, as there will be no singe
frame clock to assume is the main one. Thus, deprecate the construction
of timelines without either an actor or frame clock set.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
203c20d7ad clutter/timeline: Add way to associate a timeline to an actor
The association is inactive, as in it doesn't do anything yet, but it
will later be used to determine what frame clock should be driving the
timeline by looking at what stage view the actor is currently on.

This also adapts sub types (ClutterPropertyTransition) to have
constuctors that takes an actor just as the new ClutterTimeline
constructor.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
ff5f77f273 clutter/stage: Expose stage update helpers
This is so something outside of clutter-stage.c (i.e.
clutter-stage-view.c) can eventually do various things
_clutter_stage_do_update() does now while not redrawing the whole stage.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
fc0b8f9d9c laters: Use clutter_stage_schedule_update() instead of timeline
The MetaLater functionality needs to make sure an update is scheduled so
that it can run its callbacks etc. This used a ClutterTimeline (which is
an object more or less meant to drive animations markers, frames etc)
just to keep the master frame clock running. We're moving away from a
single master clock, so just schedule updates directly instead, with the
newly exposed API.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
1e284c601c clutter/stage-view: Move framebuffer sanity check into helper
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
5e7ce7ea75 clutter/stage-view: Move frambuffer prop setting into helper
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
69d0ff4567 clutter/stage: Move device updating to helper
It takes the list previously gathered. Freeing the list is left to the
caller using a g_autoptr.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
3944daf3c0 clutter/stage: Find devices to update after finish queue redraw
Devices are updated (repicked) as part of the stage update phase, as
their stacking, position and transform might have changed since since
the last update.

The redraw clip was used to avoid unnecessary updating of devices, if
the device in question had it's position outside of the redraw clip. If
the device coordinate was outside of the redraw clip, what was
underneith the device couldn't have changed.

What it failed to do, however, was to update devices if a relayout had
happened in the same update, as it checked the state whether a layout
had happened before attempting to do a relayout, effectively delaying
the device updating to the next update.

This commit changes the behavior to always update the device given the
complete redraw clip caused by all possible relayouts of the same update
as the device update happens in.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
b45cea301e clutter/stage: Rename find-devices-to-update function
It doesn't only update pointers, and it finds which ones to eventually
update.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
14dfe929f2 clutter/stage: Move out tracing from do_update() to callees
This makes the function a bit more cluttered, and it'll always trace
when the same functions are called from other places.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
b9a52ecfdf screen-cast: Only check queued-redraw on the relevant views
We'd check if there was any queued redraw on the stage, but this is
inappropriate for two reasons:

1) A monitor and area screen cast source only cares about damage on a
   subset of the stage.
2) The global pending-redraw is going away when paint scheduling will be
   more view centric.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
feb444402e renderer: Add API to get a view list for a monitor
Where renderer views correspond to CRTCs, this will result in a list of
those views; otherwise (i.e. X11 CM), it'll result in a list containing
the global view.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
9ed463b488 renderer-view: Keep track of what CRTC it is associated with
For the nested and native backend, it'll point to the CRTC it was
created for. On the X11 CM backend, it'll be NULL, as there is only a
single global stage view.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
33450700dc clutter/stage: Add 'pending_finish_queue_redraws' state
This will allow anyone to finish any queued redraws making their
corresponding damage end up being posted to the stage views. This will
allow units to check whether, so far, any updates are queued on a
particular stage view.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
62f251574f clutter/stage: Always check stage views when checking for full redraw
It's an optimization to check whether there are any redraws on the stage
by checking the 'redraw-pending' field. That field is going away, so
remove that optimization.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
59eebd6f6d clutter/stage-view: Pass a pointer to the stage during constuction
This is so that stage views can interact with the stage they are views
of.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
ca82cde6dd tests/frame-clock: Add test that switches frame clock mid timeline
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
9b054f4a1b clutter/timeline: Add running timeline to frameclock if it changes
It's intended that timelines can change frame clock while running; but
up until now it'd only add itself if the frame clock was set when
started.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
f31a7acab5 clutter/timeline: Add helpers to remove/add timeline to some frame clock
Either the master clock or assigned frame clock.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
a0d87662f7 tests/clutter: Add frame clock timeline test case
Tests basic functionality such as that timelines are advanced after
having added themself to frame clock.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
c302f4d379 frame-clock: Make it possible to drive timelines
Add API to add and remove ClutterTimeline objects to the frame clock.
Just as the legacy master clock, having a timeline added to the frame
clock causes the frame clock to continuously reschedule updates until
the timeline is removed.

ClutterTimeline is adapted to be able to be driven by a
ClutterFrameClock. This is done by adding a 'frame-clock' property, and
if set, the timeline will add and remove itself to the frame clock
instead of the master clock.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
3c4efd13c1 frame-clock: Pass timestamp to frame callback
The timestamp comes from the GSource, meaning it's a more accurate
representation of when the frame started to be dispatched compared to
getting the current time in any callback.

Currently unused.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
9676db4dbf clutter/master-clock: Move out private timeline declarations
They are intended to be used by other objects than the master clock, so
don't keep the declaration there.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
a132c8dc8e frame-clock: Add API to inhibit/uninhibit updates
Equivalent to pause/resume, but ref counted.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
cae5b99537 frame-clock: Add callback before the actual frame callback
Aimed to have the frame listener do things like processing events before
the actual frame. In between the before-frame and actual frame,
timelines will be advanced.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
6ffdfff9ee frame-clock: Add basic tracing
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
b18d4fc346 tests/frame-clock: Add schedule-update-now test
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
7e27fb6d56 clutter/frame-clock: Add API to schedule next frame immediately
Aimed to replace the 'skip-sync-delay' mechanism currently used by
XSyncAlarmNotify to schedule an more immediate redraw.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
8f96885af8 tests/frame-clock: Check that no damage doesn't ever dispatch
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
51ee41ee43 tests/frame-clock: Test delayed schedule update
Check that the frame clock doesn't dispatch any updates early until
there is any scheduling.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
e743b36cfc clutter/frame-clock: Handle immediate present feedback
In certain scenarios, the frame clock needs to handle present feedback
long before the assumed presentation time happens. To avoid scheduling
the next frame to soon, avoid scheduling one if we were presented half a
frame interval within the last expected presentation time.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
96a108ed4e clutter: Add a simple frame clock base
This adds a current unused, apart from tests, frame clock. It just
reschedules given a refresh rate, based on presentation time feedback.

The aiming for it is to be used with a single frame listener (stage
views) that will notify when a frame is presented. It does not aim to
handle multiple frame listeners, instead, it's assumed that different
frame listeners will use their own frame clocks.

Also add a test that verifies that the basic functionality works.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1285
2020-07-02 19:36:50 +02:00
Jonas Ådahl
da633dcc52 clutter/actor: Allocate with the same box if deferred due to transition
When a transition is created for the allocation change, it will delay
the new allocation box getting set depending on transition details.
This, however, means that e.g. the 'needs_allocation' flag never gets
cleared if a transition is created, causing other parts of the code to
get confused thinking it didn't pass through a layout step before paint.

Fix this by calling clutter_actor_allocate_internal() with the current
allocation box if a transition was created, so that we'll properly clear
'needs_allocation' flag.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1345
2020-07-02 17:35:41 +02:00
Robert Mader
86646679f1 surface-actor: Add culling offset for geometry scale - take 2
41130b08eb added a fix for culling subsurfaces with geometry scale.
Unfortunately it only did so for the opaque regions, not for clip and
unobscured regions, as the effect was hidden by bug that was only
fixed by 3187fe8ebc.

Apply the same fix to clip and unobscured regions and use the chance
to move most of the slightly hackish geometry scale related code
into a single place.

We need to scale slightly differently in the two cases, indicated by
the new `ScalePerspectiveType` enum, as the scale is dependent on the
perspective - once from outside, once from inside of the scaled actor.

Closes https://gitlab.gnome.org/GNOME/mutter/-/issues/1312
2020-06-30 20:57:57 +02:00
Jonas Dreßler
df4eeff6f2 clutter/actor: Invalidate stage-views on transformation changes
Since we now have the neccessary infrastructure to get notified about
changes to the absolute transformation matrix, we can also invalidate
the stage-views list on updates to this matrix.

So rename absolute_allocation_changed() to absolute_geometry_changed()
to make it clear this function is not only about allocations, and call
that function recursively for all children on changes to the
transformation matrix, too.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1343
2020-06-30 20:03:53 +02:00
Jonas Dreßler
64304b0b68 clutter/actor: Cache transformations applied using apply_transform vfunc
If we want to invalidate the stage-views list reliably on changes to the
actors transformation matrices, we also need to get notified about
changes to the custom transformations applied using the
apply_transform() vfunc.

So provide a new API that allows invalidating the transformation matrix
for actors implementing custom transformations, too. This in turn allows
us to cache the matrix applied using the apply_transform() vfunc by
moving responsibility of keeping track of the caching from
clutter_actor_real_apply_transform() to
_clutter_actor_apply_modelview_transform().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1343
2020-06-30 19:59:38 +02:00
Jonas Dreßler
c5159e3184 clutter/text: Enable relayout on resource-scale changes
ClutterText needs a new allocation on resource-scale changes, which we
added proper support for in the last commit, so use that API for
ClutterText.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1276
2020-06-30 13:15:53 +00:00
Jonas Dreßler
280429bac8 clutter: Add private API to support resource scale affecting layout
For ClutterText, the resource scale the text is drawn with affects the
size of the allocation: ClutterText will choose a font scale based on
the resource scale, and that font scale can lead to a slight difference
in size compared to the unscaled font.

We currently handle that by queuing a relayout inside the
"resource-scale-changed" signal handler. This solution is a bit
problematic though since it will take one more allocation cycle until
the allocation is actually updated after a scale-change, so the actor is
painted using the wrong allocation for one frame.

Also the current solution can lead to relayout loops in a few cases, for
example if a ClutterText is located near the edge on a 1x scaled monitor
and is moved to intersect a 2x scaled monitor: Now the resource scale
will change to 2 and a new allocation box is calculated; if this
allocation box is slightly smaller than the old one because of the new
font scale, the allocation won't intersect the 2x scaled monitor again
and the resource scale switches back to 1. Now the allocation gets
larger again and intersects the 2x scaled monitor again.

This commit introduces a way to properly support those actors: In case
an actors resource scale might affect its allocation, it should call the
private function clutter_actor_queue_immediate_relayout(). This will
make sure the actor gets a relayout before the upcoming paint happens
afte every resource scale change. Also potential relayout loops can
be handled by the actors themselves using a "phase" argument that's
passed to implementations of the calculate_resource_scale() vfunc.

The new API is private because resource scales are not meant to be used
in a way where the scale affects the allocation. With ClutterText and
the current behavior of Pango, that can't be avoid though, so we need it
anyway.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1276
2020-06-30 13:15:53 +00:00
Jonas Dreßler
98df2dbd05 clutter/actor: Always return a resource scale in get_resource_scale()
Since we now always return a resource scale, we can remove the boolean
return value from clutter_actor_get_resource_scale() and
_clutter_actor_get_real_resource_scale(), and instead simply return the
scale.

While at it, also remove the underscore from the
_clutter_actor_get_real_resource_scale() private API.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1276
2020-06-30 13:15:53 +00:00
Jonas Dreßler
4a72ac0516 clutter/actor: Use stage-views list for resource scales
Now that ClutterActor has a convenient API for getting the stage views
an actor is presented on, we can remove a large part of the code for
resource-scale calculation and instead rely on the stage-views list.

The way this works is a bit different from the old resource scales:
clutter_actor_get_resource_scale() always returns a scale, but this
value is only guaranteed to be correct when called from a vfunc_paint()
implementation, in all other cases the value is guessed using the scale
of the parent actor or the last valid scale. Now in case the value
previously reported by clutter_actor_get_resource_scale() turns out to
be wrong, "resource-scale-changed" will be emitted before the next paint
and the actor has a chance to update its resources.

The general idea behind this new implementation is for actors which only
need the scale during painting to continue using
clutter_actor_get_resource_scale() as they do right now, and for actors
which need the resource scale on other occasions, like during size
negotiation, to use the scale reported by
clutter_actor_get_resource_scale() but also listen to the
"resource-scale-changed" signal to eventually redo the work using the
correct scale.

The "guessing" of the scale is done with the intention of always giving
actors a scale to work with so they don't have to fall back to a scale
value the actor itself has to define, and also with the intention of
emitting the "resource-scale-changed" signal as rarely as possible, so
that when an actor is newly created, it won't have to load its resources
multiple times.

The big advantage this has over the old resource scales is that it's now
safe to call clutter_actor_get_resource_scale() from everywhere (before,
calling it from size negotiation functions would usually fail). It will
also make it a lot easier to use the resource scale for complex cases
like ClutterText without risking to get into relayout loops.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1276
2020-06-30 13:15:53 +00:00
Jonas Dreßler
802b24a640 clutter/backend: Introduce a fallback scale set to primary monitor scale
Add private API to ClutterBackend to set a fallback resource scale
available to Clutter. This API will be used for "guessing" the
resource-scale of ClutterActors in case the actor is not attached to a
stage or not properly positioned yet.

We set this value from inside mutters MetaRenderer while creating new
stage-views for each logical monitor. This makes it possible to set the
fallback scale to the scale of the primary monitor, which is the monitor
where most ClutterActors are going to be positioned.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1276
2020-06-30 13:15:53 +00:00
Jonas Dreßler
162aec7802 clutter: Replace ClutterActors resource-scale property with a signal
We're going to refactor resource scales, making the notification of
changes to the resource scale a lot more important than it is right now
(we won't guarantee queried scales are correct outside the paint cycle
anymore).

Having a separate signal/vfunc for this will make the difference between
the new clutter_actor_get_resource_scale() API (which can return a
guessed value) and the notification of changes to the resource scale
(which will be guaranteed to return an up-to-date value) more obvious.

So replace the "resource-scale" property of ClutterActor with a
"resource-scale-changed" signal that's emitted when the resource scale
is recalculated.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1276
2020-06-30 13:15:53 +00:00
Daniel van Vugt
9823a0f6c9 background-content: Fix an x/y mixup
Fortunately the coordinate is local and always (0,0) so it didn't
break anything.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1341
2020-06-30 18:37:35 +08:00
Olivier Fourdan
b8524504f4 remote-desktop: Check for screencast only when required
The portal API requires a screencast session only for absolution motion
with remote desktop, other methods including relative motion do not
require a screencast session.

There is no reason to be more strict than the API actually is, check for
a screencast session only when required, like for absolute motion events
and touch events.

Tested with https://gitlab.gnome.org/snippets/1122

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1307
2020-06-29 16:41:51 +00:00
Florian Müllner
c1933cfd09 workspace: Add :active convenience property
There are a couple of places in gnome-shell where we aren't interested
in which workspace is active, but whether a given workspace is active.

Of course it's easy to use the former to determine the latter, but we
can offer a convenience property on the workspace itself almost for
free, so let's do that.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1336
2020-06-29 14:07:20 +00:00
Robert Mader
1142f06af5 shaped-texture: Clean up set_opaque_region()
Make the code more consistent with similar functions elsewhere
and save a few cycles by removing the type check.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1334
2020-06-29 12:58:10 +02:00
Robert Mader
bb4e87bf35 shaped-texture: Make set_opaque_region() private
The shell doesn't use it and I couldn't find any extensions that does
and it probably doesn't make much sense any more these days anyway.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1334
2020-06-29 12:57:55 +02:00
Jonas Dreßler
37256cb76b clutter/box-layout: Request the correct size for homogeneous layouts
In case the layout is homogeneous, all children aligned by the box
layout must be allocated the same size. In order to fit them all inside
the container, the size request of the box layout has to look for the
child with the largest size and use that size for all children.

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

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1333
2020-06-29 12:15:06 +02:00
Jonas Dreßler
7f12099ead clutter/box-layout: Add spacing when computing opposite orientation size
ClutterBoxLayout calculates the preferred size of the opposite
orientation (so for example the height if the orientation is horizontal)
by getting the preferred size of the real orientation first, and then
the preferred size of the opposite orientation, using the other size as
for_width/height when doing the request.

Right now, for non-homogeneous layouts this for_width/height does not
adjust for the spacing set on the box layout. This leads to children
being passed a slightly larger for_width/height, which in case of
ClutterText might cause the line to not wrap when it actually should.
This in turn means we can end up with an incorrect preferred size for
the opposite orientation, leading to a wrong allocation.

So fix that and adjust for the spacing just as we do for homogeneous
layouts by subtracting the total spacing from the available size that is
distributed between children.

This fixes the wrong height of the checkbox label reported in
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2574.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1333
2020-06-29 10:07:26 +02:00
Georges Basile Stavracas Neto
88141f1483 tests: Rename actor-anchors to actor-pivot-point
The test only covers the pivot point now, rename to reflect this.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
7146a6dddb clutter/actor: Remove anchor points and gravity
Drop the bomb.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
dbce29a0ae clutter/actor: Remove scale center and gravity
They're deprecated and, as of now, unused.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
031098a43d tests: Drop anchor-related parts of the actor-anchors test
The pivot-point parts of the test are still useful, so don't completely
remove the test, only the deprecated parts of it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
dc4cb562b7 clutter/actor: Remove rotation center
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
2e086c74e7 Drop ClutterRectangle
And the correcponding CallyRectangle class.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
e884ba7f39 tests: Replace ClutterRectangle with ClutterActor
These tests were written (and copy-pasted) before ClutterActor
had an actual background-color property. As a preparation to
the removal of ClutterRectangle, replace all these rectangles
with plain actors and background colors.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
2802d359e5 Drop ClutterBox
Nobody was subclassing or using it, except for the tests. Replace
it by ClutterActor in the tests.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
d54b10b366 clutter/timeline: Remove empty deprecated header
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
d4993c4b22 clutter/stage: Remove all deprecated functions
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
ae49f89cf3 clutter/stage: Remove color property
The property is deprecated and the current implementation simply
redirects it to ClutterActor::background-color, so remove it.

Also update the tests to set the background color directly.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
ce3e293a18 clutter: Drop ClutterGroup
It is now unused.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:46 +00:00
Georges Basile Stavracas Neto
8d83dec044 clutter/stage: Subclass ClutterActor
ClutterStage is the one and only subclass of ClutterGroup, but
it overrides basically everything specific to ClutterGroup to
mimic a ClutterActor. What a waste!

Subclass ClutterActor directly and remove all the now useless
vfunc overrides from ClutterStage. Adapt CallyStage to subclass
CallyActor as well.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Georges Basile Stavracas Neto
d4953c77c3 clutter/actor: Remove clutter_actor_show_all
Actors are visible by default these days, and this function
is deprecated for a long time.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Georges Basile Stavracas Neto
237f277641 clutter/actor: Remove clutter_actor_unparent
Pretty much the same set of changes of the previous commit, but
for clutter_actor_unparent().

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Georges Basile Stavracas Neto
59e454f01e clutter/actor: Remove clutter_actor_set_parent
Replace it by clutter_actor_add_child(), and update ClutterGroup
to not emit the 'actor-added' anymore.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Georges Basile Stavracas Neto
0b4cf9c65f clutter/actor: Remove push/pop_internal declarations
They don't even exist anymore.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Georges Basile Stavracas Neto
82b710688b clutter/main: Remove clutter_get_actor_by_gid
It's unused and doesn't return anything useful these days.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Georges Basile Stavracas Neto
387a13f0ab clutter/actor: Drop depth property and functions
It is deprecated in favor of the 'z-position' property, and
the implementation itself redirects to the z-position, so
just drop it and replace all get|set_depth calls to their
z-position counterparts.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1332
2020-06-27 13:35:45 +00:00
Daniel van Vugt
e5542c3210 shaped-texture: Use the REPLACE combine function on opaque areas
We were setting the pipeline colour to all white (1.0, 1.0, 1.0, 1.0)
and so the default layer combine function multiplied each pixel
(R, G, B, A) by all ones. Obviously multiplying by one four times per
pixel is a waste of effort so we remove the colour setting *and* set
the layer combine function to a trivial shader that will ignore whatever
the current pipeline colour is set to. So now we do **zero** multiplies
per pixel.

On an i7-7700 at UHD 3840x2160 this results in 5% faster render times
and 10% lower power usage (says intel_gpu_top). The benefit is probably
much higher for virtual machines though, as they're no longer being
asked to do CPU-based math on every pixel of a window.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1331
2020-06-27 10:20:11 +00:00
Sebastian Keller
d85c3c1e94 tests/stacking: Add test for when no default focus window can be found
The previous commit removed checks for intermediate focus states which
would make tests randomly fail, because of their time dependence. What
can be tested however is that if there is no other window available that
would accept the focus, that the focus remains at 'none', after the
focused window has been closed. This newly introduced test checks the
focus directly after closing the window (and syncing) and after the time
it would have taken for the queue to finish. The first check has a
similar timing issue as the removed focus checks in the other tests, but
the test will never accidentally fail, because regardless of whether the
queue has finished or not, the focus is always expected to be 'none'.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1329
2020-06-26 21:00:12 +00:00
Sebastian Keller
d830d985c1 tests/stacking: Don't test for time-dependent intermediate focus state
While c3d13203 ensured that the test-client has actually closed the
window before testing for the focus change, it also made another timing
related issue with the tests more likely to happen. Serveral tests
assert that the focus is set to 'none' after the focussed window has
been closed when the window below does not accept focus. This however
can never be reliably tested, because closing the window triggers
timeout based iteration of a queue of default focus candidate windows.
This starts after the window has been closed and might finish before the
clients have finished synchronizing. This issue is more likely to
trigger the shorter the queue is and the more test clients there are
that could delay the synchronization.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1329
2020-06-26 21:00:12 +00:00
Jonas Ådahl
4c0aa2afca wayland/xdg-shell: Don't use xdg_surface private to get window geometry
We already used the actual API in the same function, move that call a
bit higher up to and use the variable in more places.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1295
2020-06-26 07:47:41 +00:00
Jonas Ådahl
d6af59612c wayland/shell: Apply geometry after subsurface state application
The subsurface state may affect the geometry end result, e.g. when
window decoration enlarging the toplevel window are applied. If we don't
wait with calculating the window geometry, intersecting the set region
with the subsurface tree extents will not include the subsurfaces.

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

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1295
2020-06-26 07:47:40 +00:00
Jonas Ådahl
be59b514ca wayland: Remove a couple of stray newlines
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1295
2020-06-26 07:47:40 +00:00
201 changed files with 4861 additions and 8846 deletions

27
NEWS
View File

@@ -1,3 +1,30 @@
3.37.3
======
* Support custom keyboard layouts in $XDG_CONFIG_HOME/xkb [Peter; !936]
* Optimize resource scale computation [Jonas D.; !1196, !1276, !1343]
* Allow animating ClutterActor's content property [Georges; !1301]
* Implement backgrounds as ClutterContent [Georges; !1302]
* Add ClutterAlignContraint:pivot-point property [Jonas D.; !737]
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
* Do not paint textures of fully obscured windows [Robert; !1326]
* Use a more appropriate combine function on opaque areas [Daniel; !1331]
* Fix remote desktop being broken without screencast session [Olivier; #1307]
* Remove more long-deprecated Clutter APIs [Adam, Georges; !1194, !1332]
* Drive each monitor by its own frame clock [Jonas Å.; !1285]
* Fix copy/paste failures on X11 [Carlos; !1350]
* Mipmap background texture rendering [Daniel; !1347]
* Plugged memory leaks [Sebastian, Jonas D.; !1293, !1281, !1304]
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Daniel, Corentin, Carlos,
Sebastian, Michel, Robert, Florian; !1288, !1289, !1291, !1296, !1292, !1298,
!1300, !1303, !1290, !1287, !1306, !1305, !1308, !1313, !1250, !1314, !1267,
!1275, !1317, !1270, !1322, !1181, !1282, !1325, !1323, !1240, !1295, !1329,
!1333, !1334, !1336, !1341, #1312, !1345, !1349, !1356, #873, !1310, !1357]
Contributors:
Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho,
Peter Hutterer, Adam Jackson, Sebastian Keller, Robert Mader, Florian Müllner,
Georges Basile Stavracas Neto, Corentin Noël, Daniel van Vugt, Jonas Ådahl
3.37.2
======
* Fix move-to-center keybinding with multiple monitors [Sergey; #1073]

View File

@@ -1,147 +0,0 @@
/* 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

@@ -1,87 +0,0 @@
/* 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

@@ -1,98 +0,0 @@
/* 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

@@ -1,84 +0,0 @@
/* 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,
cally_stage,
CALLY_TYPE_GROUP,
CALLY_TYPE_ACTOR,
G_ADD_PRIVATE (CallyStage)
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
cally_stage_window_interface_init));

View File

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

View File

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

View File

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

View File

@@ -110,35 +110,12 @@ typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor
typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor,
gpointer user_data);
typedef struct _AnchorCoord AnchorCoord;
typedef struct _SizeRequest SizeRequest;
typedef struct _ClutterLayoutInfo ClutterLayoutInfo;
typedef struct _ClutterTransformInfo ClutterTransformInfo;
typedef struct _ClutterAnimationInfo ClutterAnimationInfo;
/* Internal helper struct to represent a point that can be stored in
either direct pixel coordinates or as a fraction of the actor's
size. It is used for the anchor point, scale center and rotation
centers. */
struct _AnchorCoord
{
gboolean is_fractional;
union
{
/* Used when is_fractional == TRUE */
struct
{
gdouble x;
gdouble y;
} fraction;
/* Use when is_fractional == FALSE */
graphene_point3d_t units;
} v;
};
struct _SizeRequest
{
guint age;
@@ -183,24 +160,15 @@ ClutterLayoutInfo * _clutter_actor_peek_layout_info
struct _ClutterTransformInfo
{
/* rotation (angle and center) */
/* rotation */
gdouble rx_angle;
AnchorCoord rx_center;
gdouble ry_angle;
AnchorCoord ry_center;
gdouble rz_angle;
AnchorCoord rz_center;
/* scaling */
gdouble scale_x;
gdouble scale_y;
gdouble scale_z;
AnchorCoord scale_center;
/* anchor point */
AnchorCoord anchor;
/* translation */
graphene_point3d_t translation;
@@ -315,13 +283,15 @@ void _clutter_actor_queue_relayout_on_clones
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
float *resource_scale);
float clutter_actor_get_real_resource_scale (ClutterActor *actor);
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
CoglTexture *texture);
void clutter_actor_update_stage_views (ClutterActor *self);
void clutter_actor_update_stage_views (ClutterActor *self,
int phase);
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@@ -142,11 +142,6 @@ struct _ClutterActor
* ClutterActorClass:
* @show: signal class handler for #ClutterActor::show; it must chain
* up to the parent's implementation
* @show_all: virtual function for containers and composite actors, to
* determine which children should be shown when calling
* clutter_actor_show_all() on the actor. Defaults to calling
* clutter_actor_show(). This virtual function is deprecated and it
* should not be overridden.
* @hide: signal class handler for #ClutterActor::hide; it must chain
* up to the parent's implementation
* @hide_all: virtual function for containers and composite actors, to
@@ -183,7 +178,10 @@ struct _ClutterActor
* implementation.
* @apply_transform: virtual function, used when applying the transformations
* to an actor before painting it or when transforming coordinates or
* the allocation; it must chain up to the parent's implementation
* the allocation; if the transformation calculated by this function may
* have changed, the cached transformation must be invalidated by calling
* clutter_actor_invalidate_transform(); it must chain up to the parent's
* implementation
* @parent_set: signal class handler for the #ClutterActor::parent-set
* @destroy: signal class handler for #ClutterActor::destroy. It must
* chain up to the parent's implementation
@@ -226,7 +224,6 @@ struct _ClutterActorClass
/*< public >*/
void (* show) (ClutterActor *self);
void (* show_all) (ClutterActor *self);
void (* hide) (ClutterActor *self);
void (* hide_all) (ClutterActor *self);
void (* realize) (ClutterActor *self);
@@ -302,6 +299,9 @@ struct _ClutterActorClass
gboolean (* touch_event) (ClutterActor *self,
ClutterTouchEvent *event);
gboolean (* has_accessible) (ClutterActor *self);
void (* resource_scale_changed) (ClutterActor *self);
float (* calculate_resource_scale) (ClutterActor *self,
int phase);
/*< private >*/
/* padding for future expansion */
@@ -419,7 +419,9 @@ CLUTTER_EXPORT
void clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box);
CLUTTER_EXPORT
void clutter_actor_allocate_preferred_size (ClutterActor *self);
void clutter_actor_allocate_preferred_size (ClutterActor *self,
float x,
float y);
CLUTTER_EXPORT
void clutter_actor_allocate_available_size (ClutterActor *self,
gfloat x,
@@ -454,6 +456,10 @@ void clutter_actor_set_position
gfloat x,
gfloat y);
CLUTTER_EXPORT
gboolean clutter_actor_get_fixed_position (ClutterActor *self,
float *x,
float *y);
CLUTTER_EXPORT
void clutter_actor_get_position (ClutterActor *self,
gfloat *x,
gfloat *y);
@@ -593,8 +599,7 @@ gboolean clutter_actor_get_paint_box
ClutterActorBox *box);
CLUTTER_EXPORT
gboolean clutter_actor_get_resource_scale (ClutterActor *self,
gfloat *resource_scale);
float clutter_actor_get_resource_scale (ClutterActor *self);
CLUTTER_EXPORT
gboolean clutter_actor_has_overlaps (ClutterActor *self);
@@ -922,6 +927,12 @@ void clutter_actor_pick_box (ClutterActor *self,
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
#endif /* __CLUTTER_ACTOR_H__ */

View File

@@ -194,3 +194,25 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
else
return clutter_interval_compute_value (interval, progress, value);
}
/**
* clutter_animatable_get_actor:
* @animatable: a #ClutterAnimatable
*
* Get animated actor.
*
* Return value: (transfer none): a #ClutterActor
*/
ClutterActor *
clutter_animatable_get_actor (ClutterAnimatable *animatable)
{
ClutterAnimatableInterface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
g_return_val_if_fail (iface->get_actor, NULL);
return iface->get_actor (animatable);
}

View File

@@ -50,6 +50,7 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
* animatable property
* @interpolate_value: virtual function for interpolating the progress
* of a property
* @get_actor: virtual function for getting associated actor
*
* Since: 1.0
*/
@@ -72,6 +73,7 @@ struct _ClutterAnimatableInterface
ClutterInterval *interval,
gdouble progress,
GValue *value);
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
};
CLUTTER_EXPORT
@@ -92,6 +94,9 @@ gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
gdouble progress,
GValue *value);
CLUTTER_EXPORT
ClutterActor * clutter_animatable_get_actor (ClutterAnimatable *animatable);
G_END_DECLS
#endif /* __CLUTTER_ANIMATABLE_H__ */

View File

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

View File

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

@@ -38,12 +38,14 @@
*
* |[<!-- language="C" -->
* // source
* rect[0] = clutter_rectangle_new_with_color (&red_color);
* rect[0] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[0], &red_color);
* clutter_actor_set_position (rect[0], x_pos, y_pos);
* clutter_actor_set_size (rect[0], 100, 100);
*
* // second rectangle
* rect[1] = clutter_rectangle_new_with_color (&green_color);
* rect[1] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[1], &green_color);
* clutter_actor_set_size (rect[1], 100, 100);
* clutter_actor_set_opacity (rect[1], 0);
*
@@ -53,7 +55,8 @@
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
*
* // third rectangle
* rect[2] = clutter_rectangle_new_with_color (&blue_color);
* rect[2] = clutter_actor_new ();
* clutter_actor_set_background_color (rect[2], &blue_color);
* clutter_actor_set_size (rect[2], 100, 100);
* clutter_actor_set_opacity (rect[2], 0);
*

View File

@@ -167,8 +167,10 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
ClutterActor *child;
gint n_children = 0;
gfloat minimum, natural;
float largest_min_size, largest_nat_size;
minimum = natural = 0;
largest_min_size = largest_nat_size = 0;
clutter_actor_iter_init (&iter, container);
while (clutter_actor_iter_next (&iter, &child))
@@ -183,8 +185,22 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
get_child_size (child, priv->orientation,
for_size, &child_min, &child_nat);
minimum += child_min;
natural += child_nat;
if (priv->is_homogeneous)
{
largest_min_size = MAX (largest_min_size, child_min);
largest_nat_size = MAX (largest_nat_size, child_nat);
}
else
{
minimum += child_min;
natural += child_nat;
}
}
if (priv->is_homogeneous)
{
minimum = largest_min_size * n_children;
natural = largest_nat_size * n_children;
}
if (n_children > 1)
@@ -315,6 +331,8 @@ get_preferred_size_for_opposite_orientation (ClutterBoxLayout *self,
}
else
{
size -= (nvis_children - 1) * priv->spacing;
/* Bring children up to size first */
if (isnormal (size) || size == 0)
{

View File

@@ -245,7 +245,13 @@ clutter_clone_allocate (ClutterActor *self,
*/
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
!clutter_actor_has_allocation (priv->clone_source))
clutter_actor_allocate_preferred_size (priv->clone_source);
{
float x = 0.f;
float y = 0.f;
clutter_actor_get_fixed_position (priv->clone_source, &x, &y);
clutter_actor_allocate_preferred_size (priv->clone_source, x, y);
}
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
@@ -262,6 +268,7 @@ clutter_clone_allocate (ClutterActor *self,
{
priv->x_scale = x_scale;
priv->y_scale = y_scale;
clutter_actor_invalidate_transform (CLUTTER_ACTOR (self));
}
#if 0

View File

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

View File

@@ -139,7 +139,11 @@ clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
child != NULL;
child = clutter_actor_get_next_sibling (child))
{
clutter_actor_allocate_preferred_size (child);
float x = 0.f;
float y = 0.f;
clutter_actor_get_fixed_position (child, &x, &y);
clutter_actor_allocate_preferred_size (child, x, y);
}
}

View File

@@ -0,0 +1,550 @@
/*
* 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

@@ -0,0 +1,87 @@
/*
* 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

@@ -1,96 +0,0 @@
/*
* 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

@@ -32,8 +32,7 @@
* it has been paired, and it controls the allocation of its children.
*
* Any composite or container #ClutterActor subclass can delegate the
* layouting of its children to a #ClutterLayoutManager. Clutter provides
* a generic container using #ClutterLayoutManager called #ClutterBox.
* layouting of its children to a #ClutterLayoutManager.
*
* Clutter provides some simple #ClutterLayoutManager sub-classes, like
* #ClutterFlowLayout and #ClutterBinLayout.
@@ -97,7 +96,7 @@
*
* |[
* {
* "type" : "ClutterBox",
* "type" : "ClutterActor",
* "layout-manager" : { "type" : "ClutterGridLayout" },
* "children" : [
* {

View File

@@ -61,7 +61,6 @@
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-graphene.h"
#include "clutter-main.h"
#include "clutter-master-clock.h"
#include "clutter-mutter.h"
#include "clutter-paint-node-private.h"
#include "clutter-private.h"
@@ -83,10 +82,6 @@
/* main context */
static ClutterMainContext *ClutterCntx = NULL;
G_LOCK_DEFINE_STATIC (ClutterCntx);
/* main lock and locking/unlocking functions */
static GMutex clutter_threads_mutex;
/* command line options */
static gboolean clutter_is_initialized = FALSE;
@@ -145,12 +140,6 @@ static const GDebugKey clutter_paint_debug_keys[] = {
{ "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 DEBUG_GROUP "Debug"
@@ -519,11 +508,7 @@ clutter_main (void)
main_loops = g_slist_prepend (main_loops, loop);
if (g_main_loop_is_running (main_loops->data))
{
_clutter_threads_release_lock ();
g_main_loop_run (loop);
_clutter_threads_acquire_lock ();
}
g_main_loop_run (loop);
main_loops = g_slist_remove (main_loops, loop);
@@ -540,13 +525,9 @@ _clutter_threads_dispatch (gpointer data)
ClutterThreadsDispatch *dispatch = data;
gboolean ret = FALSE;
_clutter_threads_acquire_lock ();
if (!g_source_is_destroyed (g_main_current_source ()))
ret = dispatch->func (dispatch->data);
_clutter_threads_release_lock ();
return ret;
}
@@ -771,40 +752,6 @@ clutter_threads_add_timeout (guint interval,
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
_clutter_context_is_initialized (void)
{
@@ -814,8 +761,8 @@ _clutter_context_is_initialized (void)
return ClutterCntx->is_initialized;
}
static ClutterMainContext *
clutter_context_get_default_unlocked (void)
ClutterMainContext *
_clutter_context_get_default (void)
{
if (G_UNLIKELY (ClutterCntx == NULL))
{
@@ -846,20 +793,6 @@ clutter_context_get_default_unlocked (void)
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
clutter_arg_direction_cb (const char *key,
const char *value,
@@ -2156,27 +2089,6 @@ _clutter_process_event (ClutterEvent *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
clutter_base_init (void)
{
@@ -2191,9 +2103,6 @@ clutter_base_init (void)
g_type_init ();
#endif
/* initialise the Big Clutter Lock™ if necessary */
clutter_threads_init_default ();
clutter_graphene_init ();
}
}
@@ -2261,9 +2170,7 @@ clutter_threads_remove_repaint_func (guint handle_id)
g_return_if_fail (handle_id > 0);
_clutter_context_lock ();
context = clutter_context_get_default_unlocked ();
context = _clutter_context_get_default ();
l = context->repaint_funcs;
while (l != NULL)
{
@@ -2286,8 +2193,6 @@ clutter_threads_remove_repaint_func (guint handle_id)
l = l->next;
}
_clutter_context_unlock ();
}
/**
@@ -2386,9 +2291,7 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
g_return_val_if_fail (func != NULL, 0);
_clutter_context_lock ();
context = clutter_context_get_default_unlocked ();
context = _clutter_context_get_default ();
repaint_func = g_slice_new (ClutterRepaintFunction);
@@ -2402,8 +2305,6 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
context->repaint_funcs = g_list_prepend (context->repaint_funcs,
repaint_func);
_clutter_context_unlock ();
return repaint_func->id;
}

View File

@@ -1,618 +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/>.
*/
/*
* 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 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 = 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

@@ -1,48 +0,0 @@
/*
* 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

@@ -1,132 +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/>.
*/
/*
* 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

@@ -1,69 +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_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

@@ -39,6 +39,10 @@
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
void clutter_set_custom_backend_func (ClutterBackend *(* func) (void));
@@ -68,12 +72,6 @@ gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
ClutterPaintFlag paint_flags,
GError **error);
CLUTTER_EXPORT
void clutter_stage_freeze_updates (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_thaw_updates (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_clear_stage_views (ClutterStage *stage);

View File

@@ -238,8 +238,8 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
gfloat stage_width, stage_height;
gfloat target_width = -1, target_height = -1;
CoglFramebuffer *framebuffer;
gfloat resource_scale;
gfloat ceiled_resource_scale;
float resource_scale;
float ceiled_resource_scale;
graphene_point3d_t local_offset;
gfloat old_viewport[4];
@@ -254,17 +254,11 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
stage = _clutter_actor_get_stage_internal (priv->actor);
clutter_actor_get_size (stage, &stage_width, &stage_height);
if (_clutter_actor_get_real_resource_scale (priv->actor, &resource_scale))
{
ceiled_resource_scale = ceilf (resource_scale);
stage_width *= 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 ();
}
resource_scale = clutter_actor_get_real_resource_scale (priv->actor);
ceiled_resource_scale = ceilf (resource_scale);
stage_width *= ceiled_resource_scale;
stage_height *= ceiled_resource_scale;
/* 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
@@ -417,8 +411,9 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
*/
cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) &&
resource_scale != 1.0f)
resource_scale = clutter_actor_get_resource_scale (priv->actor);
if (resource_scale != 1.0f)
{
float paint_scale = 1.0f / resource_scale;
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);

View File

@@ -1412,6 +1412,7 @@ clutter_layer_node_new (const CoglMatrix *projection,
{
ClutterLayerNode *res;
CoglContext *context;
CoglTexture2D *tex_2d;
CoglTexture *texture;
CoglColor color;
@@ -1426,9 +1427,10 @@ clutter_layer_node_new (const CoglMatrix *projection,
/* the texture backing the FBO */
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
texture = cogl_texture_2d_new_with_size (context,
MAX (res->fbo_width, 1),
MAX (res->fbo_height, 1));
tex_2d = cogl_texture_2d_new_with_size (context,
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));

View File

@@ -62,6 +62,7 @@
#include "clutter-gesture-action-private.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-timeline.h"
#include <math.h>
#define FLOAT_EPSILON (1e-15)
@@ -326,8 +327,12 @@ gesture_end (ClutterGestureAction *gesture,
if (ABS (velocity) * priv->acceleration_factor > min_velocity &&
duration > FLOAT_EPSILON)
{
ClutterActor *pan_actor =
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gesture));
priv->interpolated_x = priv->interpolated_y = 0.0f;
priv->deceleration_timeline = clutter_timeline_new (duration);
priv->deceleration_timeline = clutter_timeline_new_for_actor (pan_actor,
duration);
clutter_timeline_set_progress_mode (priv->deceleration_timeline,
CLUTTER_EASE_OUT_EXPO);
@@ -458,6 +463,8 @@ clutter_pan_action_set_actor (ClutterActorMeta *meta,
/* make sure we reset the state */
if (priv->state == PAN_STATE_INTERPOLATING)
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,

View File

@@ -37,7 +37,6 @@
#include "clutter-feature.h"
#include "clutter-id-pool.h"
#include "clutter-layout-manager.h"
#include "clutter-master-clock.h"
#include "clutter-settings.h"
#include "clutter-stage-manager.h"
#include "clutter-stage.h"
@@ -122,9 +121,6 @@ struct _ClutterMainContext
/* the object holding all the stage instances */
ClutterStageManager *stage_manager;
/* the clock driving all the frame operations */
ClutterMasterClock *master_clock;
/* the main event queue */
GQueue *events_queue;
@@ -177,11 +173,6 @@ typedef struct
gboolean _clutter_threads_dispatch (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);
void _clutter_context_lock (void);
void _clutter_context_unlock (void);
@@ -316,6 +307,30 @@ gboolean _clutter_run_progress_function (GType gtype,
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
#endif /* __CLUTTER_PRIVATE_H__ */

View File

@@ -278,6 +278,26 @@ clutter_property_transition_init (ClutterPropertyTransition *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:
* @property_name: (allow-none): a property of @animatable, or %NULL

View File

@@ -78,8 +78,13 @@ struct _ClutterPropertyTransitionClass
CLUTTER_EXPORT
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
ClutterTransition * clutter_property_transition_new (const char *property_name);
CLUTTER_EXPORT
void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition,
const char *property_name);

View File

@@ -50,14 +50,14 @@
* <informalexample><programlisting><![CDATA[
* {
* "id" : "red-button",
* "type" : "ClutterRectangle",
* "type" : "ClutterActor",
* "width" : 100,
* "height" : 100,
* "color" : "&num;ff0000ff"
* "background-color" : "&num;ff0000ff"
* }
* ]]></programlisting></informalexample>
*
* This will produce a red #ClutterRectangle, 100x100 pixels wide, and
* This will produce a red #ClutterActor, 100x100 pixels wide, and
* with a ClutterScript id of "red-button"; it can be retrieved by calling:
*
* |[

View File

@@ -40,7 +40,14 @@ void clutter_stage_paint_view (ClutterStage
ClutterStageView *view,
const cairo_region_t *redraw_clip);
void _clutter_stage_emit_after_paint (ClutterStage *stage);
void clutter_stage_emit_before_update (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
void _clutter_stage_set_window (ClutterStage *stage,
@@ -58,9 +65,12 @@ void _clutter_stage_get_viewport (ClutterStage
void _clutter_stage_dirty_viewport (ClutterStage *stage);
void _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
ClutterStageView *view);
void _clutter_stage_maybe_relayout (ClutterActor *stage);
gboolean _clutter_stage_needs_update (ClutterStage *stage);
gboolean _clutter_stage_do_update (ClutterStage *stage);
void clutter_stage_maybe_relayout (ClutterActor *stage);
void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
GSList * clutter_stage_find_updated_devices (ClutterStage *stage);
void clutter_stage_update_devices (ClutterStage *stage,
GSList *devices);
void clutter_stage_update_actor_stage_views (ClutterStage *stage);
CLUTTER_EXPORT
void _clutter_stage_queue_event (ClutterStage *stage,
@@ -69,8 +79,6 @@ void _clutter_stage_queue_event (ClutterStage *stage,
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
void _clutter_stage_process_queued_events (ClutterStage *stage);
void _clutter_stage_update_input_devices (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);
void clutter_stage_log_pick (ClutterStage *stage,
@@ -126,16 +134,21 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
void _clutter_stage_set_scale_factor (ClutterStage *stage,
int factor);
void _clutter_stage_presented (ClutterStage *stage,
CoglFrameEvent frame_event,
void clutter_stage_presented (ClutterStage *stage,
ClutterStageView *view,
ClutterFrameInfo *frame_info);
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
ClutterActor *actor);
void clutter_stage_dequeue_actor_relayout (ClutterStage *stage,
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
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View File

@@ -19,6 +19,7 @@
#define __CLUTTER_STAGE_VIEW_PRIVATE_H__
#include "clutter/clutter-stage-view.h"
#include "clutter/clutter-types.h"
void clutter_stage_view_after_paint (ClutterStageView *view,
cairo_region_t *redraw_clip);
@@ -62,4 +63,12 @@ void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView
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__ */

View File

@@ -24,8 +24,10 @@
#include <math.h>
#include "clutter/clutter-damage-history.h"
#include "clutter/clutter-frame-clock.h"
#include "clutter/clutter-private.h"
#include "clutter/clutter-mutter.h"
#include "clutter/clutter-stage-private.h"
#include "cogl/cogl.h"
enum
@@ -33,11 +35,13 @@ enum
PROP_0,
PROP_NAME,
PROP_STAGE,
PROP_LAYOUT,
PROP_FRAMEBUFFER,
PROP_OFFSCREEN,
PROP_USE_SHADOWFB,
PROP_SCALE,
PROP_REFRESH_RATE,
PROP_LAST
};
@@ -48,6 +52,8 @@ typedef struct _ClutterStageViewPrivate
{
char *name;
ClutterStage *stage;
cairo_rectangle_int_t layout;
float scale;
CoglFramebuffer *framebuffer;
@@ -71,6 +77,9 @@ typedef struct _ClutterStageViewPrivate
gboolean has_redraw_clip;
cairo_region_t *redraw_clip;
float refresh_rate;
ClutterFrameClock *frame_clock;
guint dirty_viewport : 1;
guint dirty_projection : 1;
} ClutterStageViewPrivate;
@@ -102,9 +111,9 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
clutter_stage_view_get_instance_private (view);
if (priv->offscreen)
return priv->offscreen;
return COGL_FRAMEBUFFER (priv->offscreen);
else if (priv->shadow.framebuffer)
return priv->shadow.framebuffer;
return COGL_FRAMEBUFFER (priv->shadow.framebuffer);
else
return priv->framebuffer;
}
@@ -127,8 +136,9 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
}
static CoglPipeline *
clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen);
CoglPipeline *pipeline;
pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
@@ -137,7 +147,7 @@ clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
COGL_PIPELINE_FILTER_NEAREST,
COGL_PIPELINE_FILTER_NEAREST);
cogl_pipeline_set_layer_texture (pipeline, 0,
cogl_offscreen_get_texture (framebuffer));
cogl_offscreen_get_texture (offscreen));
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
@@ -158,7 +168,7 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
return;
priv->offscreen_pipeline =
clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
clutter_stage_view_create_offscreen_pipeline (priv->offscreen);
if (view_class->setup_offscreen_blit_pipeline)
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
@@ -192,7 +202,7 @@ clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view
static void
paint_transformed_framebuffer (ClutterStageView *view,
CoglPipeline *pipeline,
CoglFramebuffer *src_framebuffer,
CoglOffscreen *src_framebuffer,
CoglFramebuffer *dst_framebuffer,
const cairo_region_t *redraw_clip)
{
@@ -432,10 +442,13 @@ clutter_stage_view_after_paint (ClutterStageView *view,
if (priv->shadow.framebuffer)
{
CoglFramebuffer *shadowfb =
COGL_FRAMEBUFFER (priv->shadow.framebuffer);
paint_transformed_framebuffer (view,
priv->offscreen_pipeline,
priv->offscreen,
priv->shadow.framebuffer,
shadowfb,
redraw_clip);
}
else
@@ -508,7 +521,7 @@ find_damaged_tiles (ClutterStageView *view,
stride = cogl_dma_buf_handle_get_stride (current_dma_buf_handle);
bpp = cogl_dma_buf_handle_get_bpp (current_dma_buf_handle);
cogl_framebuffer_finish (priv->shadow.framebuffer);
cogl_framebuffer_finish (COGL_FRAMEBUFFER (priv->shadow.framebuffer));
if (!cogl_dma_buf_handle_sync_read_start (prev_dma_buf_handle, error))
return NULL;
@@ -601,7 +614,7 @@ swap_dma_buf_framebuffer (ClutterStageView *view)
clutter_stage_view_get_instance_private (view);
int next_idx;
CoglDmaBufHandle *next_dma_buf_handle;
CoglOffscreen *next_framebuffer;
CoglFramebuffer *next_framebuffer;
next_idx = ((priv->shadow.dma_buf.current_idx + 1) %
G_N_ELEMENTS (priv->shadow.dma_buf.handles));
@@ -697,12 +710,13 @@ copy_shadowfb_to_onscreen (ClutterStageView *view,
for (i = 0; i < cairo_region_num_rectangles (damage_region); i++)
{
CoglFramebuffer *shadowfb = COGL_FRAMEBUFFER (priv->shadow.framebuffer);
g_autoptr (GError) error = NULL;
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (damage_region, i, &rect);
if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
if (!cogl_blit_framebuffer (shadowfb,
priv->framebuffer,
rect.x, rect.y,
rect.x, rect.y,
@@ -754,7 +768,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
if (priv->offscreen)
{
callback (priv->offscreen, user_data);
callback (COGL_FRAMEBUFFER (priv->offscreen), user_data);
}
else if (priv->shadow.framebuffer)
{
@@ -773,7 +787,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
}
else
{
callback (priv->shadow.framebuffer, user_data);
callback (COGL_FRAMEBUFFER (priv->shadow.framebuffer), user_data);
}
}
else
@@ -988,6 +1002,154 @@ clutter_stage_view_take_scanout (ClutterStageView *view)
return g_steal_pointer (&priv->next_scanout);
}
void
clutter_stage_view_schedule_update (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
clutter_frame_clock_schedule_update (priv->frame_clock);
}
float
clutter_stage_view_get_refresh_rate (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
return priv->refresh_rate;
}
/**
* clutter_stage_view_get_frame_clock: (skip)
*/
ClutterFrameClock *
clutter_stage_view_get_frame_clock (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
return priv->frame_clock;
}
static void
handle_frame_clock_before_frame (ClutterFrameClock *frame_clock,
int64_t frame_count,
gpointer user_data)
{
ClutterStageView *view = user_data;
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
_clutter_stage_process_queued_events (priv->stage);
}
static ClutterFrameResult
handle_frame_clock_frame (ClutterFrameClock *frame_clock,
int64_t frame_count,
int64_t time_us,
gpointer user_data)
{
ClutterStageView *view = user_data;
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
ClutterStage *stage = priv->stage;
g_autoptr (GSList) devices = NULL;
ClutterFrameResult result;
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
return CLUTTER_FRAME_RESULT_IDLE;
if (!clutter_actor_is_realized (CLUTTER_ACTOR (stage)))
return CLUTTER_FRAME_RESULT_IDLE;
if (!clutter_actor_is_mapped (CLUTTER_ACTOR (stage)))
return CLUTTER_FRAME_RESULT_IDLE;
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT);
clutter_stage_emit_before_update (stage, view);
clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
clutter_stage_update_actor_stage_views (stage);
clutter_stage_maybe_finish_queue_redraws (stage);
devices = clutter_stage_find_updated_devices (stage);
if (clutter_stage_view_has_redraw_clip (view))
{
ClutterStageWindow *stage_window;
clutter_stage_emit_before_paint (stage, view);
stage_window = _clutter_stage_get_window (stage);
_clutter_stage_window_redraw_view (stage_window, view);
clutter_stage_emit_after_paint (stage, view);
_clutter_stage_window_finish_frame (stage_window);
result = CLUTTER_FRAME_RESULT_PENDING_PRESENTED;
}
else
{
result = CLUTTER_FRAME_RESULT_IDLE;
}
clutter_stage_update_devices (stage, devices);
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
clutter_stage_emit_after_update (stage, view);
return result;
}
static const ClutterFrameListenerIface frame_clock_listener_iface = {
.before_frame = handle_frame_clock_before_frame,
.frame = handle_frame_clock_frame,
};
void
clutter_stage_view_notify_presented (ClutterStageView *view,
ClutterFrameInfo *frame_info)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
clutter_stage_presented (priv->stage, view, frame_info);
clutter_frame_clock_notify_presented (priv->frame_clock, frame_info);
}
static void
sanity_check_framebuffer (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
G_GNUC_UNUSED int fb_width, fb_height;
fb_width = cogl_framebuffer_get_width (priv->framebuffer);
fb_height = cogl_framebuffer_get_height (priv->framebuffer);
g_warn_if_fail (fabsf (roundf (fb_width / priv->scale) -
fb_width / priv->scale) < FLT_EPSILON);
g_warn_if_fail (fabsf (roundf (fb_height / priv->scale) -
fb_height / priv->scale) < FLT_EPSILON);
}
static void
clutter_stage_view_set_framebuffer (ClutterStageView *view,
CoglFramebuffer *framebuffer)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
g_warn_if_fail (!priv->framebuffer);
if (framebuffer)
{
priv->framebuffer = cogl_object_ref (framebuffer);
sanity_check_framebuffer (view);
}
}
static void
clutter_stage_view_get_property (GObject *object,
guint prop_id,
@@ -1003,6 +1165,9 @@ clutter_stage_view_get_property (GObject *object,
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
case PROP_STAGE:
g_value_set_boxed (value, &priv->stage);
break;
case PROP_LAYOUT:
g_value_set_boxed (value, &priv->layout);
break;
@@ -1018,6 +1183,9 @@ clutter_stage_view_get_property (GObject *object,
case PROP_SCALE:
g_value_set_float (value, priv->scale);
break;
case PROP_REFRESH_RATE:
g_value_set_float (value, priv->refresh_rate);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -1039,26 +1207,15 @@ clutter_stage_view_set_property (GObject *object,
case PROP_NAME:
priv->name = g_value_dup_string (value);
break;
case PROP_STAGE:
priv->stage = g_value_get_object (value);
break;
case PROP_LAYOUT:
layout = g_value_get_boxed (value);
priv->layout = *layout;
break;
case PROP_FRAMEBUFFER:
priv->framebuffer = g_value_dup_boxed (value);
#ifndef G_DISABLE_CHECKS
if (priv->framebuffer)
{
int fb_width, fb_height;
fb_width = cogl_framebuffer_get_width (priv->framebuffer);
fb_height = cogl_framebuffer_get_height (priv->framebuffer);
g_warn_if_fail (fabsf (roundf (fb_width / priv->scale) -
fb_width / priv->scale) < FLT_EPSILON);
g_warn_if_fail (fabsf (roundf (fb_height / priv->scale) -
fb_height / priv->scale) < FLT_EPSILON);
}
#endif
clutter_stage_view_set_framebuffer (view, g_value_get_boxed (value));
break;
case PROP_OFFSCREEN:
priv->offscreen = g_value_dup_boxed (value);
@@ -1069,6 +1226,9 @@ clutter_stage_view_set_property (GObject *object,
case PROP_SCALE:
priv->scale = g_value_get_float (value);
break;
case PROP_REFRESH_RATE:
priv->refresh_rate = g_value_get_float (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -1084,6 +1244,10 @@ clutter_stage_view_constructed (GObject *object)
if (priv->use_shadowfb)
init_shadowfb (view);
priv->frame_clock = clutter_frame_clock_new (priv->refresh_rate,
&frame_clock_listener_iface,
view);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->constructed (object);
}
@@ -1110,6 +1274,7 @@ clutter_stage_view_dispose (GObject *object)
g_clear_pointer (&priv->offscreen, cogl_object_unref);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
g_clear_pointer (&priv->frame_clock, clutter_frame_clock_destroy);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
}
@@ -1123,6 +1288,7 @@ clutter_stage_view_init (ClutterStageView *view)
priv->dirty_viewport = TRUE;
priv->dirty_projection = TRUE;
priv->scale = 1.0;
priv->refresh_rate = 60.0;
}
static void
@@ -1146,6 +1312,16 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_STAGE] =
g_param_spec_object ("stage",
"The stage",
"The ClutterStage",
CLUTTER_TYPE_STAGE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_LAYOUT] =
g_param_spec_boxed ("layout",
"View layout",
@@ -1191,5 +1367,14 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_REFRESH_RATE] =
g_param_spec_float ("refresh-rate",
"Refresh rate",
"Update refresh rate",
1.0, G_MAXFLOAT, 60.0,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
}

View File

@@ -27,6 +27,7 @@
#include <cogl/cogl.h>
#include "clutter-macros.h"
#include "clutter-frame-clock.h"
#define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ())
CLUTTER_EXPORT
@@ -69,4 +70,7 @@ CLUTTER_EXPORT
void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
CoglMatrix *matrix);
CLUTTER_EXPORT
ClutterFrameClock * clutter_stage_view_get_frame_clock (ClutterStageView *view);
#endif /* __CLUTTER_STAGE_VIEW_H__ */

View File

@@ -103,81 +103,12 @@ _clutter_stage_window_get_geometry (ClutterStageWindow *window,
}
void
_clutter_stage_window_schedule_update (ClutterStageWindow *window,
int sync_delay)
_clutter_stage_window_redraw_view (ClutterStageWindow *window,
ClutterStageView *view)
{
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
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);
}
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);
CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view);
}
gboolean

View File

@@ -44,12 +44,8 @@ struct _ClutterStageWindowInterface
void (* get_geometry) (ClutterStageWindow *stage_window,
cairo_rectangle_int_t *geometry);
void (* schedule_update) (ClutterStageWindow *stage_window,
int sync_delay);
gint64 (* get_update_time) (ClutterStageWindow *stage_window);
void (* clear_update_time) (ClutterStageWindow *stage_window);
void (* redraw) (ClutterStageWindow *stage_window);
void (* redraw_view) (ClutterStageWindow *stage_window,
ClutterStageView *view);
gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window);
@@ -78,15 +74,12 @@ void _clutter_stage_window_resize (ClutterStageWin
CLUTTER_EXPORT
void _clutter_stage_window_get_geometry (ClutterStageWindow *window,
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,
gboolean accept_focus);
void _clutter_stage_window_redraw (ClutterStageWindow *window);
void _clutter_stage_window_redraw_view (ClutterStageWindow *window,
ClutterStageView *view);
gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window);

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."
#endif
#include <clutter/clutter-actor.h>
#include <clutter/clutter-types.h>
#include <clutter/clutter-group.h>
#include <clutter/clutter-stage-view.h>
G_BEGIN_DECLS
@@ -56,7 +56,7 @@ typedef struct _ClutterStagePrivate ClutterStagePrivate;
struct _ClutterStage
{
/*< private >*/
ClutterGroup parent_instance;
ClutterActor parent_instance;
ClutterStagePrivate *priv;
};
@@ -74,7 +74,7 @@ struct _ClutterStage
struct _ClutterStageClass
{
/*< private >*/
ClutterGroupClass parent_class;
ClutterActorClass parent_class;
/*< public >*/
/* signals */
@@ -197,7 +197,8 @@ CLUTTER_EXPORT
void clutter_stage_ensure_viewport (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_stage_is_redraw_queued (ClutterStage *stage);
gboolean clutter_stage_is_redraw_queued_on_view (ClutterStage *stage,
ClutterStageView *view);
#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API
CLUTTER_EXPORT

View File

@@ -187,9 +187,6 @@ struct _ClutterTextPrivate
ClutterInputContentHintFlags input_hints;
ClutterInputContentPurpose input_purpose;
/* Signal handler for when the :resource-scale changes */
gulong resource_scale_changed_id;
/* bitfields */
guint alignment : 2;
guint wrap : 1;
@@ -598,9 +595,7 @@ ensure_effective_pango_scale_attribute (ClutterText *self)
float resource_scale;
ClutterTextPrivate *priv = self->priv;
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale) ||
resource_scale == 1.0)
return;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
if (priv->effective_attrs != NULL)
{
@@ -922,18 +917,6 @@ clutter_text_direction_changed_cb (GObject *gobject,
/* 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:
* @text: a #ClutterText
@@ -1137,8 +1120,7 @@ maybe_create_text_layout_with_resource_scale (ClutterText *text,
{
float resource_scale;
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale))
return NULL;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (text));
return create_text_layout_with_scale (text,
allocation_width,
@@ -1170,8 +1152,7 @@ clutter_text_coords_to_position (ClutterText *self,
g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0);
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return 0;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
/* Take any offset due to scrolling into account, and normalize
* the coordinates to PangoScale units
@@ -1299,8 +1280,7 @@ clutter_text_position_to_coords (ClutterText *self,
g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE);
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return FALSE;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
ret = clutter_text_position_to_coords_internal (self, position,
x, y, line_height);
@@ -1776,7 +1756,6 @@ clutter_text_dispose (GObject *gobject)
clutter_text_dirty_cache (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,
clutter_get_default_backend ());
@@ -2641,8 +2620,7 @@ clutter_text_paint (ClutterActor *self,
!clutter_text_should_draw_cursor (text))
return;
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return;
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
clutter_actor_box_scale (&alloc, resource_scale);
clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height);
@@ -2874,8 +2852,7 @@ clutter_text_get_paint_volume (ClutterActor *self,
if (!clutter_actor_has_allocation (self))
return FALSE;
if (!clutter_actor_get_resource_scale (self, &resource_scale))
return FALSE;
resource_scale = clutter_actor_get_resource_scale (self);
_clutter_paint_volume_init_static (&priv->paint_volume, self);
@@ -2932,8 +2909,7 @@ clutter_text_get_preferred_width (ClutterActor *self,
gfloat layout_width;
gfloat resource_scale;
if (!clutter_actor_get_resource_scale (self, &resource_scale))
resource_scale = 1;
resource_scale = clutter_actor_get_resource_scale (self);
layout = clutter_text_create_layout (text, -1, -1);
pango_layout_get_extents (layout, NULL, &logical_rect);
@@ -2989,8 +2965,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
gfloat layout_height;
gfloat resource_scale;
if (!clutter_actor_get_resource_scale (self, &resource_scale))
resource_scale = 1;
resource_scale = clutter_actor_get_resource_scale (self);
if (priv->single_line_mode)
for_width = -1;
@@ -3066,6 +3041,33 @@ clutter_text_has_overlaps (ClutterActor *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
clutter_text_im_focus (ClutterText *text)
{
@@ -3814,6 +3816,8 @@ clutter_text_class_init (ClutterTextClass *klass)
actor_class->key_focus_in = clutter_text_key_focus_in;
actor_class->key_focus_out = clutter_text_key_focus_out;
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:
@@ -4621,11 +4625,6 @@ clutter_text_init (ClutterText *self)
NULL);
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);
}
/**

View File

@@ -0,0 +1,33 @@
/*
* 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

@@ -95,22 +95,31 @@
#include "clutter-build-config.h"
#include "clutter-timeline.h"
#include "deprecated/clutter-timeline.h"
#include "clutter-debug.h"
#include "clutter-easing.h"
#include "clutter-enum-types.h"
#include "clutter-frame-clock.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-master-clock.h"
#include "clutter-private.h"
#include "clutter-scriptable.h"
#include "deprecated/clutter-timeline.h"
#include "clutter-timeline-private.h"
struct _ClutterTimelinePrivate
{
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;
/* The total length in milliseconds of this timeline */
@@ -172,12 +181,14 @@ enum
{
PROP_0,
PROP_ACTOR,
PROP_DELAY,
PROP_DURATION,
PROP_DIRECTION,
PROP_AUTO_REVERSE,
PROP_REPEAT_COUNT,
PROP_PROGRESS_MODE,
PROP_FRAME_CLOCK,
PROP_LAST
};
@@ -198,6 +209,8 @@ enum
static guint timeline_signals[LAST_SIGNAL] = { 0, };
static void update_frame_clock (ClutterTimeline *timeline);
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT,
@@ -289,6 +302,177 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline,
g_hash_table_insert (priv->markers_by_name, marker->name, marker);
}
static void
on_actor_destroyed (ClutterActor *actor,
ClutterTimeline *timeline)
{
ClutterTimelinePrivate *priv = timeline->priv;
priv->actor = NULL;
}
/**
* clutter_timeline_get_actor:
* @timeline: a #ClutterTimeline
*
* 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;
}
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 */
typedef struct _ParseClosure {
ClutterTimeline *timeline;
@@ -430,6 +614,10 @@ clutter_timeline_set_property (GObject *object,
switch (prop_id)
{
case PROP_ACTOR:
clutter_timeline_set_actor (timeline, g_value_get_object (value));
break;
case PROP_DELAY:
clutter_timeline_set_delay (timeline, g_value_get_uint (value));
break;
@@ -454,6 +642,10 @@ clutter_timeline_set_property (GObject *object,
clutter_timeline_set_progress_mode (timeline, g_value_get_enum (value));
break;
case PROP_FRAME_CLOCK:
clutter_timeline_set_frame_clock (timeline, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -471,6 +663,10 @@ clutter_timeline_get_property (GObject *object,
switch (prop_id)
{
case PROP_ACTOR:
g_value_set_object (value, priv->actor);
break;
case PROP_DELAY:
g_value_set_uint (value, priv->delay);
break;
@@ -495,6 +691,10 @@ clutter_timeline_get_property (GObject *object,
g_value_set_enum (value, priv->progress_mode);
break;
case PROP_FRAME_CLOCK:
g_value_set_object (value, priv->frame_clock);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -506,16 +706,14 @@ clutter_timeline_finalize (GObject *object)
{
ClutterTimeline *self = CLUTTER_TIMELINE (object);
ClutterTimelinePrivate *priv = self->priv;
ClutterMasterClock *master_clock;
if (priv->markers_by_name)
g_hash_table_destroy (priv->markers_by_name);
if (priv->is_playing)
{
master_clock = _clutter_master_clock_get_default ();
_clutter_master_clock_remove_timeline (master_clock, self);
}
maybe_remove_timeline (self);
g_clear_object (&priv->frame_clock);
G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object);
}
@@ -530,6 +728,14 @@ clutter_timeline_dispose (GObject *object)
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)
{
priv->progress_notify (priv->progress_data);
@@ -546,6 +752,18 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
/**
* ClutterTimeline::actor:
*
* The actor the timeline is associated with. This will determine what frame
* clock will drive it.
*/
obj_props[PROP_ACTOR] =
g_param_spec_object ("actor",
P_("Actor"),
P_("Associated ClutterActor"),
CLUTTER_TYPE_ACTOR,
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
/**
* ClutterTimeline:delay:
*
@@ -644,6 +862,18 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
CLUTTER_LINEAR,
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->finalize = clutter_timeline_finalize;
object_class->set_property = clutter_timeline_set_property;
@@ -926,7 +1156,6 @@ set_is_playing (ClutterTimeline *timeline,
gboolean is_playing)
{
ClutterTimelinePrivate *priv = timeline->priv;
ClutterMasterClock *master_clock;
is_playing = !!is_playing;
@@ -935,15 +1164,17 @@ set_is_playing (ClutterTimeline *timeline,
priv->is_playing = is_playing;
master_clock = _clutter_master_clock_get_default ();
if (priv->is_playing)
{
priv->waiting_first_tick = TRUE;
priv->current_repeat = 0;
_clutter_master_clock_add_timeline (master_clock, timeline);
maybe_add_timeline (timeline);
}
else
_clutter_master_clock_remove_timeline (master_clock, timeline);
{
maybe_remove_timeline (timeline);
}
}
static gboolean
@@ -1140,6 +1371,9 @@ clutter_timeline_start (ClutterTimeline *timeline)
if (priv->duration == 0)
return;
g_warn_if_fail ((priv->actor && clutter_actor_get_stage (priv->actor)) ||
priv->frame_clock);
if (priv->delay)
priv->delay_id = clutter_threads_add_timeout (priv->delay,
delay_timeout_func,
@@ -1340,6 +1574,46 @@ clutter_timeline_new (guint duration_ms)
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);
}
/**
* clutter_timeline_get_delay:
* @timeline: a #ClutterTimeline
@@ -1602,7 +1876,7 @@ _clutter_timeline_do_tick (ClutterTimeline *timeline,
/* Check the is_playing variable before performing the timeline tick.
* This is necessary, as if a timeline is stopped in response to a
* master-clock generated signal of a different timeline, this code can
* frame clock generated signal of a different timeline, this code can
* still be reached.
*/
if (!priv->is_playing)
@@ -2420,3 +2694,32 @@ clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
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,7 +119,19 @@ CLUTTER_EXPORT
GType clutter_timeline_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterTimeline * clutter_timeline_new (guint duration_ms);
ClutterTimeline * clutter_timeline_new_for_actor (ClutterActor *actor,
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
guint clutter_timeline_get_duration (ClutterTimeline *timeline);
@@ -221,6 +233,13 @@ gint64 clutter_timeline_get_duration_hint
CLUTTER_EXPORT
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
#endif /* _CLUTTER_TIMELINE_H__ */

View File

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

View File

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

View File

@@ -57,6 +57,7 @@ typedef struct _ClutterActorIter ClutterActorIter;
typedef struct _ClutterPaintNode ClutterPaintNode;
typedef struct _ClutterContent ClutterContent; /* dummy */
typedef struct _ClutterScrollActor ClutterScrollActor;
typedef struct _ClutterFrameClock ClutterFrameClock;
typedef struct _ClutterInterval ClutterInterval;
typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */

View File

@@ -63,9 +63,9 @@
#include "clutter-feature.h"
#include "clutter-fixed-layout.h"
#include "clutter-flow-layout.h"
#include "clutter-frame-clock.h"
#include "clutter-gesture-action.h"
#include "clutter-grid-layout.h"
#include "clutter-group.h"
#include "clutter-image.h"
#include "clutter-input-device.h"
#include "clutter-input-device-tool.h"

View File

@@ -47,6 +47,7 @@
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-stage-view-private.h"
#include "cogl.h"
#define MAX_STACK_RECTS 256
@@ -55,17 +56,25 @@ typedef struct _ClutterStageViewCoglPrivate
/* Damage history, in stage view render target framebuffer coordinate space.
*/
ClutterDamageHistory *damage_history;
guint notify_presented_handle_id;
} ClutterStageViewCoglPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl,
CLUTTER_TYPE_STAGE_VIEW)
typedef struct _ClutterStageCoglPrivate
{
int64_t global_frame_counter;
} ClutterStageCoglPrivate;
static void
clutter_stage_window_iface_init (ClutterStageWindowInterface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
_clutter_stage_cogl,
G_TYPE_OBJECT,
G_ADD_PRIVATE (ClutterStageCogl)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
@@ -77,67 +86,12 @@ enum
PROP_LAST
};
static void
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
gint sync_delay);
static void
clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
{
CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_window);
}
void
_clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl,
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info)
{
if (frame_event == COGL_FRAME_EVENT_SYNC)
{
/* Early versions of the swap_event implementation in Mesa
* deliver BufferSwapComplete event when not selected for,
* so if we get a swap event we aren't expecting, just ignore it.
*
* https://bugs.freedesktop.org/show_bug.cgi?id=27962
*
* FIXME: This issue can be hidden inside Cogl so we shouldn't
* need to care about this bug here.
*/
if (stage_cogl->pending_swaps > 0)
stage_cogl->pending_swaps--;
}
else if (frame_event == COGL_FRAME_EVENT_COMPLETE)
{
gint64 presentation_time_cogl = frame_info->presentation_time;
if (presentation_time_cogl != 0)
{
ClutterBackend *backend = stage_cogl->backend;
CoglContext *context = clutter_backend_get_cogl_context (backend);
gint64 current_time_cogl = cogl_get_clock_time (context);
gint64 now = g_get_monotonic_time ();
stage_cogl->last_presentation_time =
now + (presentation_time_cogl - current_time_cogl) / 1000;
}
stage_cogl->refresh_rate = frame_info->refresh_rate;
}
_clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info);
if (frame_event == COGL_FRAME_EVENT_COMPLETE &&
stage_cogl->update_time != -1)
{
ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl);
stage_cogl->update_time = -1;
clutter_stage_cogl_schedule_update (stage_window,
stage_cogl->last_sync_delay);
}
}
static gboolean
clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
{
@@ -158,101 +112,14 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
return TRUE;
}
static void
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
gint sync_delay)
static int64_t
clutter_stage_cogl_get_frame_counter (ClutterStageWindow *stage_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
gint64 now;
float refresh_rate;
gint64 refresh_interval;
int64_t min_render_time_allowed;
int64_t max_render_time_allowed;
int64_t next_presentation_time;
ClutterStageCoglPrivate *priv =
_clutter_stage_cogl_get_instance_private (stage_cogl);
if (stage_cogl->update_time != -1)
return;
stage_cogl->last_sync_delay = sync_delay;
now = g_get_monotonic_time ();
if (sync_delay < 0)
{
stage_cogl->update_time = now;
return;
}
refresh_rate = stage_cogl->refresh_rate;
if (refresh_rate <= 0.0)
refresh_rate = clutter_get_default_frame_rate ();
refresh_interval = (gint64) (0.5 + G_USEC_PER_SEC / refresh_rate);
if (refresh_interval == 0)
{
stage_cogl->update_time = now;
return;
}
min_render_time_allowed = refresh_interval / 2;
max_render_time_allowed = refresh_interval - 1000 * sync_delay;
/* Be robust in the case of incredibly bogus refresh rate */
if (max_render_time_allowed <= 0)
{
g_warning ("Unsupported monitor refresh rate detected. "
"(Refresh rate: %.3f, refresh interval: %" G_GINT64_FORMAT ")",
refresh_rate,
refresh_interval);
stage_cogl->update_time = now;
return;
}
if (min_render_time_allowed > max_render_time_allowed)
min_render_time_allowed = max_render_time_allowed;
next_presentation_time = stage_cogl->last_presentation_time + refresh_interval;
/* Get next_presentation_time closer to its final value, to reduce
* the number of while iterations below.
*/
if (next_presentation_time < now)
{
int64_t last_virtual_presentation_time = now - now % refresh_interval;
int64_t hardware_clock_phase =
stage_cogl->last_presentation_time % refresh_interval;
next_presentation_time =
last_virtual_presentation_time + hardware_clock_phase;
}
while (next_presentation_time < now + min_render_time_allowed)
next_presentation_time += refresh_interval;
stage_cogl->update_time = next_presentation_time - max_render_time_allowed;
if (stage_cogl->update_time == stage_cogl->last_update_time)
stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval;
}
static gint64
clutter_stage_cogl_get_update_time (ClutterStageWindow *stage_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
if (stage_cogl->pending_swaps)
return -1; /* in the future, indefinite */
return stage_cogl->update_time;
}
static void
clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
stage_cogl->last_update_time = stage_cogl->update_time;
stage_cogl->update_time = -1;
return priv->global_frame_counter;
}
static ClutterActor *
@@ -355,12 +222,35 @@ paint_damage_region (ClutterStageWindow *stage_window,
cogl_framebuffer_pop_matrix (framebuffer);
}
typedef struct _NotifyPresentedClosure
{
ClutterStageView *view;
ClutterFrameInfo frame_info;
} NotifyPresentedClosure;
static gboolean
notify_presented_idle (gpointer user_data)
{
NotifyPresentedClosure *closure = user_data;
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (closure->view);
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
view_priv->notify_presented_handle_id = 0;
clutter_stage_view_notify_presented (closure->view, &closure->frame_info);
return G_SOURCE_REMOVE;
}
static void
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region,
gboolean swap_with_damage)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterStageCoglPrivate *priv =
_clutter_stage_cogl_get_instance_private (stage_cogl);
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
clutter_stage_view_before_swap_buffer (view, swap_region);
@@ -369,6 +259,7 @@ swap_framebuffer (ClutterStageWindow *stage_window,
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
int *damage, n_rects, i;
CoglFrameInfo *frame_info;
n_rects = cairo_region_num_rectangles (swap_region);
damage = g_newa (int, n_rects * 4);
@@ -383,6 +274,9 @@ swap_framebuffer (ClutterStageWindow *stage_window,
damage[i * 4 + 3] = rect.height;
}
frame_info = cogl_frame_info_new (priv->global_frame_counter);
priv->global_frame_counter++;
/* push on the screen */
if (n_rects > 0 && !swap_with_damage)
{
@@ -391,9 +285,8 @@ swap_framebuffer (ClutterStageWindow *stage_window,
onscreen);
cogl_onscreen_swap_region (onscreen,
damage, n_rects);
return FALSE;
damage, n_rects,
frame_info);
}
else
{
@@ -401,18 +294,35 @@ swap_framebuffer (ClutterStageWindow *stage_window,
onscreen);
cogl_onscreen_swap_buffers_with_damage (onscreen,
damage, n_rects);
return TRUE;
damage, n_rects,
frame_info);
}
}
else
{
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
NotifyPresentedClosure *closure;
CLUTTER_NOTE (BACKEND, "cogl_framebuffer_finish (framebuffer: %p)",
framebuffer);
cogl_framebuffer_finish (framebuffer);
return FALSE;
closure = g_new0 (NotifyPresentedClosure, 1);
closure->view = view;
closure->frame_info = (ClutterFrameInfo) {
.frame_counter = priv->global_frame_counter,
.refresh_rate = clutter_stage_view_get_refresh_rate (view),
.presentation_time = g_get_monotonic_time (),
};
priv->global_frame_counter++;
g_warn_if_fail (view_priv->notify_presented_handle_id == 0);
view_priv->notify_presented_handle_id =
g_idle_add_full (G_PRIORITY_DEFAULT,
notify_presented_idle,
closure, g_free);
}
}
@@ -539,11 +449,11 @@ is_buffer_age_enabled (void)
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
}
static gboolean
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
ClutterStageView *view)
static void
clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl,
ClutterStageView *view)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl);
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
@@ -562,7 +472,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
float fb_scale;
int fb_width, fb_height;
int buffer_age = 0;
gboolean res;
clutter_stage_view_get_layout (view, &view_rect);
fb_scale = clutter_stage_view_get_scale (view);
@@ -629,7 +538,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
redraw_clip = cairo_region_create_rectangle (&view_rect);
}
g_return_val_if_fail (!cairo_region_is_empty (fb_clip_region), FALSE);
g_return_if_fail (!cairo_region_is_empty (fb_clip_region));
swap_with_damage = FALSE;
if (has_buffer_age)
@@ -730,14 +639,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
cairo_region_destroy (queued_redraw_clip);
}
res = swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage);
swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage);
cairo_region_destroy (swap_region);
return res;
}
static void
@@ -745,62 +652,34 @@ clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl,
ClutterStageView *view,
CoglScanout *scanout)
{
ClutterStageCoglPrivate *priv =
_clutter_stage_cogl_get_instance_private (stage_cogl);
CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
CoglOnscreen *onscreen;
CoglFrameInfo *frame_info;
g_return_if_fail (cogl_is_onscreen (framebuffer));
onscreen = COGL_ONSCREEN (framebuffer);
cogl_onscreen_direct_scanout (onscreen, scanout);
frame_info = cogl_frame_info_new (priv->global_frame_counter);
priv->global_frame_counter++;
cogl_onscreen_direct_scanout (onscreen, scanout, frame_info);
}
static void
clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
ClutterStageView *view)
{
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
gboolean swap_event = FALSE;
GList *l;
g_autoptr (CoglScanout) scanout = NULL;
COGL_TRACE_BEGIN (ClutterStageCoglRedraw, "Paint (Cogl Redraw)");
for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next)
{
ClutterStageView *view = l->data;
g_autoptr (CoglScanout) scanout = NULL;
if (!clutter_stage_view_has_redraw_clip (view))
continue;
scanout = clutter_stage_view_take_scanout (view);
if (scanout)
{
clutter_stage_cogl_scanout_view (stage_cogl,
view,
scanout);
swap_event = TRUE;
}
else
{
swap_event |= clutter_stage_cogl_redraw_view (stage_window, view);
}
}
_clutter_stage_emit_after_paint (stage_cogl->wrapper);
_clutter_stage_window_finish_frame (stage_window);
if (swap_event)
{
/* If we have swap buffer events then cogl_onscreen_swap_buffers
* will return immediately and we need to track that there is a
* swap in progress... */
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
stage_cogl->pending_swaps++;
}
stage_cogl->frame_count++;
COGL_TRACE_END (ClutterStageCoglRedraw);
scanout = clutter_stage_view_take_scanout (view);
if (scanout)
clutter_stage_cogl_scanout_view (stage_cogl, view, scanout);
else
clutter_stage_cogl_redraw_view_primary (stage_cogl, view);
}
static void
@@ -812,10 +691,8 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
iface->resize = clutter_stage_cogl_resize;
iface->show = clutter_stage_cogl_show;
iface->hide = clutter_stage_cogl_hide;
iface->schedule_update = clutter_stage_cogl_schedule_update;
iface->get_update_time = clutter_stage_cogl_get_update_time;
iface->clear_update_time = clutter_stage_cogl_clear_update_time;
iface->redraw = clutter_stage_cogl_redraw;
iface->get_frame_counter = clutter_stage_cogl_get_frame_counter;
iface->redraw_view = clutter_stage_cogl_redraw_view;
}
static void
@@ -856,10 +733,43 @@ _clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
static void
_clutter_stage_cogl_init (ClutterStageCogl *stage)
{
stage->last_presentation_time = 0;
stage->refresh_rate = 0.0;
}
stage->update_time = -1;
static void
frame_cb (CoglOnscreen *onscreen,
CoglFrameEvent frame_event,
CoglFrameInfo *frame_info,
void *user_data)
{
ClutterStageView *view = user_data;
ClutterFrameInfo clutter_frame_info;
if (frame_event == COGL_FRAME_EVENT_SYNC)
return;
clutter_frame_info = (ClutterFrameInfo) {
.frame_counter = cogl_frame_info_get_global_frame_counter (frame_info),
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info),
.presentation_time = ns2us (cogl_frame_info_get_presentation_time (frame_info)),
};
clutter_stage_view_notify_presented (view, &clutter_frame_info);
}
static void
on_framebuffer_set (ClutterStageView *view)
{
CoglFramebuffer *framebuffer;
framebuffer = clutter_stage_view_get_onscreen (view);
if (framebuffer && cogl_is_onscreen (framebuffer))
{
cogl_onscreen_add_frame_callback (COGL_ONSCREEN (framebuffer),
frame_cb,
view,
NULL);
}
}
static void
@@ -869,6 +779,7 @@ clutter_stage_view_cogl_finalize (GObject *object)
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
g_clear_handle_id (&view_priv->notify_presented_handle_id, g_source_remove);
clutter_damage_history_free (view_priv->damage_history);
G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->finalize (object);
@@ -881,6 +792,9 @@ clutter_stage_view_cogl_init (ClutterStageViewCogl *view_cogl)
clutter_stage_view_cogl_get_instance_private (view_cogl);
view_priv->damage_history = clutter_damage_history_new ();
g_signal_connect (view_cogl, "notify::framebuffer",
G_CALLBACK (on_framebuffer_set), NULL);
}
static void

View File

@@ -41,20 +41,6 @@ struct _ClutterStageCogl
/* back pointer to the backend */
ClutterBackend *backend;
float refresh_rate;
int pending_swaps;
gint64 last_presentation_time;
gint64 update_time;
int64_t last_update_time;
/* We only enable clipped redraws after 2 frames, since we've seen
* a lot of drivers can struggle to get going and may output some
* junk frames to start with. */
unsigned int frame_count;
gint last_sync_delay;
};
struct _ClutterStageCoglClass

View File

@@ -1,114 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
* Copyright (C) 2009, 2010 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_ACTOR_DEPRECATED_H__
#define __CLUTTER_ACTOR_DEPRECATED_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
CLUTTER_DEPRECATED
ClutterActor * clutter_get_actor_by_gid (guint32 id_);
CLUTTER_DEPRECATED_FOR(clutter_actor_add_child)
void clutter_actor_set_parent (ClutterActor *self,
ClutterActor *parent);
CLUTTER_DEPRECATED_FOR(clutter_actor_remove_child)
void clutter_actor_unparent (ClutterActor *self);
CLUTTER_DEPRECATED
void clutter_actor_push_internal (ClutterActor *self);
CLUTTER_DEPRECATED
void clutter_actor_pop_internal (ClutterActor *self);
CLUTTER_DEPRECATED
void clutter_actor_show_all (ClutterActor *self);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_z_position)
void clutter_actor_set_depth (ClutterActor *self,
gfloat depth);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_z_position)
gfloat clutter_actor_get_depth (ClutterActor *self);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_rotation_angle)
void clutter_actor_set_rotation (ClutterActor *self,
ClutterRotateAxis axis,
gdouble angle,
gfloat x,
gfloat y,
gfloat z);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_rotation_angle and clutter_actor_set_pivot_point)
void clutter_actor_set_z_rotation_from_gravity (ClutterActor *self,
gdouble angle,
ClutterGravity gravity);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_rotation_angle)
gdouble clutter_actor_get_rotation (ClutterActor *self,
ClutterRotateAxis axis,
gfloat *x,
gfloat *y,
gfloat *z);
CLUTTER_DEPRECATED
ClutterGravity clutter_actor_get_z_rotation_gravity (ClutterActor *self);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_scale and clutter_actor_set_pivot_point)
void clutter_actor_set_scale_full (ClutterActor *self,
gdouble scale_x,
gdouble scale_y,
gfloat center_x,
gfloat center_y);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_pivot_point)
void clutter_actor_get_scale_center (ClutterActor *self,
gfloat *center_x,
gfloat *center_y);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_pivot_point)
ClutterGravity clutter_actor_get_scale_gravity (ClutterActor *self);
CLUTTER_DEPRECATED
void clutter_actor_set_anchor_point (ClutterActor *self,
gfloat anchor_x,
gfloat anchor_y);
CLUTTER_DEPRECATED
void clutter_actor_move_anchor_point (ClutterActor *self,
gfloat anchor_x,
gfloat anchor_y);
CLUTTER_DEPRECATED
ClutterGravity clutter_actor_get_anchor_point_gravity (ClutterActor *self);
CLUTTER_DEPRECATED
void clutter_actor_set_anchor_point_from_gravity (ClutterActor *self,
ClutterGravity gravity);
CLUTTER_DEPRECATED
void clutter_actor_move_anchor_point_from_gravity (ClutterActor *self,
ClutterGravity gravity);
G_END_DECLS
#endif /* __CLUTTER_ACTOR_DEPRECATED_H__ */

View File

@@ -1,745 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009,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>
*/
/**
* SECTION:clutter-box
* @short_description: A Generic layout container
*
* #ClutterBox is a #ClutterActor sub-class implementing the #ClutterContainer
* interface. A Box delegates the whole size requisition and size allocation to
* a #ClutterLayoutManager instance.
*
* #ClutterBox is available since Clutter 1.2
*
* #ClutterBox is deprecated since Clutter 1.10; all its relevant API is provided
* by #ClutterActor, via the #ClutterActor:layout-manager property.
*
* ## Using ClutterBox
*
* The following code shows how to create a #ClutterBox with
* a #ClutterLayoutManager sub-class, and how to add children to
* it via clutter_box_pack().
*
* |[<!-- language="C" -->
* ClutterActor *box;
* ClutterLayoutManager *layout;
*
* // Create the layout manager first
* layout = clutter_box_layout_new ();
* clutter_box_layout_set_homogeneous (CLUTTER_BOX_LAYOUT (layout), TRUE);
* clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12);
*
* // Then create the ClutterBox actor. The Box will take
* // ownership of the ClutterLayoutManager instance by sinking
* // its floating reference
* box = clutter_box_new (layout);
*
* // Now add children to the Box using the variadic arguments
* // function clutter_box_pack() to set layout properties
* clutter_box_pack (CLUTTER_BOX (box), actor,
* "x-align", CLUTTER_BOX_ALIGNMENT_CENTER,
* "y-align", CLUTTER_BOX_ALIGNMENT_END,
* "expand", TRUE,
* NULL);
* ]|
*
* #ClutterBox's clutter_box_pack() wraps the generic
* clutter_container_add_actor() function, but it also allows setting
* layout properties while adding the new child to the box.
*/
#include "clutter-build-config.h"
#include <glib-object.h>
#include <gobject/gvaluecollector.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-container.h"
#include "clutter-box.h"
#include "clutter-actor-private.h"
#include "clutter-color.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
struct _ClutterBoxPrivate
{
ClutterLayoutManager *manager;
guint changed_id;
};
enum
{
PROP_0,
PROP_COLOR,
PROP_COLOR_SET,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
static const ClutterColor default_box_color = { 255, 255, 255, 255 };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBox, clutter_box, CLUTTER_TYPE_ACTOR)
static inline void
clutter_box_set_color_internal (ClutterBox *box,
const ClutterColor *color)
{
clutter_actor_set_background_color (CLUTTER_ACTOR (box), color);
g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR_SET]);
g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR]);
}
static gboolean
clutter_box_real_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
gboolean retval = FALSE;
ClutterActorIter iter;
ClutterActor *child;
/* if we have a background color, and an allocation, then we need to
* set it as the base of our paint volume
*/
retval = clutter_paint_volume_set_from_allocation (volume, actor);
/* bail out early if we don't have any child */
if (clutter_actor_get_n_children (actor) == 0)
return retval;
retval = TRUE;
/* otherwise, union the paint volumes of our children, in case
* any one of them decides to paint outside the parent's allocation
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
const ClutterPaintVolume *child_volume;
/* This gets the paint volume of the child transformed into the
* group's coordinate space... */
child_volume = clutter_actor_get_transformed_paint_volume (child, actor);
if (!child_volume)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
return retval;
}
static void
clutter_box_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBox *self = CLUTTER_BOX (gobject);
switch (prop_id)
{
case PROP_COLOR:
clutter_box_set_color_internal (self, clutter_value_get_color (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_box_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
case PROP_COLOR:
{
ClutterColor color;
clutter_actor_get_background_color (CLUTTER_ACTOR (gobject),
&color);
clutter_value_set_color (value, &color);
}
break;
case PROP_COLOR_SET:
{
gboolean color_set;
g_object_get (gobject, "background-color-set", &color_set, NULL);
g_value_set_boolean (value, color_set);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_box_real_destroy (ClutterActor *actor)
{
ClutterActor *iter;
iter = clutter_actor_get_first_child (actor);
while (iter != NULL)
{
ClutterActor *next = clutter_actor_get_next_sibling (iter);
clutter_actor_destroy (iter);
iter = next;
}
}
static void
clutter_box_class_init (ClutterBoxClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->destroy = clutter_box_real_destroy;
actor_class->get_paint_volume = clutter_box_real_get_paint_volume;
gobject_class->set_property = clutter_box_set_property;
gobject_class->get_property = clutter_box_get_property;
/**
* ClutterBox:color:
*
* The color to be used to paint the background of the
* #ClutterBox. Setting this property will set the
* #ClutterBox:color-set property as a side effect
*
* This property sets the #ClutterActor:background-color property
* internally.
*
* Since: 1.2
*
* Deprecated: 1.10: Use the #ClutterActor:background-color property
*/
obj_props[PROP_COLOR] =
clutter_param_spec_color ("color",
P_("Color"),
P_("The background color of the box"),
&default_box_color,
CLUTTER_PARAM_READWRITE);
/**
* ClutterBox:color-set:
*
* Whether the #ClutterBox:color property has been set.
*
* This property reads the #ClutterActor:background-color-set property
* internally.
*
* Since: 1.2
*
* Deprecated: 1.10: Use the #ClutterActor:background-color-set property
*/
obj_props[PROP_COLOR_SET] =
g_param_spec_boolean ("color-set",
P_("Color Set"),
P_("Whether the background color is set"),
FALSE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
}
static void
clutter_box_init (ClutterBox *self)
{
self->priv = clutter_box_get_instance_private (self);
}
/**
* clutter_box_new:
* @manager: a #ClutterLayoutManager
*
* Creates a new #ClutterBox. The children of the box will be layed
* out by the passed @manager
*
* Return value: the newly created #ClutterBox actor
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_new() instead.
*/
ClutterActor *
clutter_box_new (ClutterLayoutManager *manager)
{
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL);
return g_object_new (CLUTTER_TYPE_BOX,
"layout-manager", manager,
NULL);
}
/**
* clutter_box_set_layout_manager:
* @box: a #ClutterBox
* @manager: a #ClutterLayoutManager
*
* Sets the #ClutterLayoutManager for @box
*
* A #ClutterLayoutManager is a delegate object that controls the
* layout of the children of @box
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_set_layout_manager() instead.
*/
void
clutter_box_set_layout_manager (ClutterBox *box,
ClutterLayoutManager *manager)
{
clutter_actor_set_layout_manager (CLUTTER_ACTOR (box), manager);
}
/**
* clutter_box_get_layout_manager:
* @box: a #ClutterBox
*
* Retrieves the #ClutterLayoutManager instance used by @box
*
* Return value: (transfer none): a #ClutterLayoutManager. The returned
* #ClutterLayoutManager is owned by the #ClutterBox and it should not
* be unreferenced
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_get_layout_manager() instead.
*/
ClutterLayoutManager *
clutter_box_get_layout_manager (ClutterBox *box)
{
return clutter_actor_get_layout_manager (CLUTTER_ACTOR (box));
}
/**
* clutter_box_packv:
* @box: a #ClutterBox
* @actor: a #ClutterActor
* @n_properties: the number of properties to set
* @properties: (array length=n_properties) (element-type utf8): a vector
* containing the property names to set
* @values: (array length=n_properties): a vector containing the property
* values to set
*
* Vector-based variant of clutter_box_pack(), intended for language
* bindings to use
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_add_child() instead. To set
* specific layout properties, use clutter_layout_manager_child_set()
*/
void
clutter_box_packv (ClutterBox *box,
ClutterActor *actor,
guint n_properties,
const gchar * const properties[],
const GValue *values)
{
ClutterLayoutManager *manager;
ClutterContainer *container;
ClutterLayoutMeta *meta;
GObjectClass *klass;
gint i;
g_return_if_fail (CLUTTER_IS_BOX (box));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
container = CLUTTER_CONTAINER (box);
clutter_container_add_actor (container, actor);
manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box));
if (manager == NULL)
return;
meta = clutter_layout_manager_get_child_meta (manager,
container,
actor);
if (meta == NULL)
return;
klass = G_OBJECT_GET_CLASS (meta);
for (i = 0; i < n_properties; i++)
{
const gchar *pname = properties[i];
GParamSpec *pspec;
pspec = g_object_class_find_property (klass, pname);
if (pspec == NULL)
{
g_warning ("%s: the layout property '%s' for managers "
"of type '%s' (meta type '%s') does not exist",
G_STRLOC,
pname,
G_OBJECT_TYPE_NAME (manager),
G_OBJECT_TYPE_NAME (meta));
break;
}
if (!(pspec->flags & G_PARAM_WRITABLE))
{
g_warning ("%s: the layout property '%s' for managers "
"of type '%s' (meta type '%s') is not writable",
G_STRLOC,
pspec->name,
G_OBJECT_TYPE_NAME (manager),
G_OBJECT_TYPE_NAME (meta));
break;
}
clutter_layout_manager_child_set_property (manager,
container, actor,
pname, &values[i]);
}
}
static inline void
clutter_box_set_property_valist (ClutterBox *box,
ClutterActor *actor,
const gchar *first_property,
va_list var_args)
{
ClutterContainer *container = CLUTTER_CONTAINER (box);
ClutterLayoutManager *manager;
ClutterLayoutMeta *meta;
GObjectClass *klass;
const gchar *pname;
manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box));
if (manager == NULL)
return;
meta = clutter_layout_manager_get_child_meta (manager,
container,
actor);
if (meta == NULL)
return;
klass = G_OBJECT_GET_CLASS (meta);
pname = first_property;
while (pname)
{
GValue value = { 0, };
GParamSpec *pspec;
gchar *error;
pspec = g_object_class_find_property (klass, pname);
if (pspec == NULL)
{
g_warning ("%s: the layout property '%s' for managers "
"of type '%s' (meta type '%s') does not exist",
G_STRLOC,
pname,
G_OBJECT_TYPE_NAME (manager),
G_OBJECT_TYPE_NAME (meta));
break;
}
if (!(pspec->flags & G_PARAM_WRITABLE))
{
g_warning ("%s: the layout property '%s' for managers "
"of type '%s' (meta type '%s') is not writable",
G_STRLOC,
pspec->name,
G_OBJECT_TYPE_NAME (manager),
G_OBJECT_TYPE_NAME (meta));
break;
}
G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec),
var_args, 0,
&error);
if (error)
{
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
break;
}
clutter_layout_manager_child_set_property (manager,
container, actor,
pspec->name, &value);
g_value_unset (&value);
pname = va_arg (var_args, gchar*);
}
}
/**
* clutter_box_pack:
* @box: a #ClutterBox
* @actor: a #ClutterActor
* @first_property: the name of the first property to set, or %NULL
* @...: a list of property name and value pairs, terminated by %NULL
*
* Adds @actor to @box and sets layout properties at the same time,
* if the #ClutterLayoutManager used by @box has them
*
* This function is a wrapper around clutter_container_add_actor()
* and clutter_layout_manager_child_set()
*
* Language bindings should use the vector-based clutter_box_packv()
* variant instead
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_add_child() instead. To set
* specific layout properties, use clutter_layout_manager_child_set()
*/
void
clutter_box_pack (ClutterBox *box,
ClutterActor *actor,
const gchar *first_property,
...)
{
va_list var_args;
g_return_if_fail (CLUTTER_IS_BOX (box));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
clutter_container_add_actor (CLUTTER_CONTAINER (box), actor);
if (first_property == NULL || *first_property == '\0')
return;
va_start (var_args, first_property);
clutter_box_set_property_valist (box, actor, first_property, var_args);
va_end (var_args);
}
/**
* clutter_box_pack_after:
* @box: a #ClutterBox
* @actor: a #ClutterActor
* @sibling: (allow-none): a #ClutterActor or %NULL
* @first_property: the name of the first property to set, or %NULL
* @...: a list of property name and value pairs, terminated by %NULL
*
* Adds @actor to @box, placing it after @sibling, and sets layout
* properties at the same time, if the #ClutterLayoutManager used by
* @box supports them
*
* If @sibling is %NULL then @actor is placed at the end of the
* list of children, to be allocated and painted after every other child
*
* This function is a wrapper around clutter_container_add_actor(),
* clutter_container_raise_child() and clutter_layout_manager_child_set()
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_insert_child_above() instead.
* To set specific layout properties, use clutter_layout_manager_child_set()
*/
void
clutter_box_pack_after (ClutterBox *box,
ClutterActor *actor,
ClutterActor *sibling,
const gchar *first_property,
...)
{
va_list var_args;
g_return_if_fail (CLUTTER_IS_BOX (box));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling));
clutter_container_add_actor (CLUTTER_CONTAINER (box), actor);
clutter_container_raise_child (CLUTTER_CONTAINER (box), actor, sibling);
if (first_property == NULL || *first_property == '\0')
return;
va_start (var_args, first_property);
clutter_box_set_property_valist (box, actor, first_property, var_args);
va_end (var_args);
}
/**
* clutter_box_pack_before:
* @box: a #ClutterBox
* @actor: a #ClutterActor
* @sibling: (allow-none): a #ClutterActor or %NULL
* @first_property: the name of the first property to set, or %NULL
* @...: a list of property name and value pairs, terminated by %NULL
*
* Adds @actor to @box, placing it before @sibling, and sets layout
* properties at the same time, if the #ClutterLayoutManager used by
* @box supports them
*
* If @sibling is %NULL then @actor is placed at the beginning of the
* list of children, to be allocated and painted below every other child
*
* This function is a wrapper around clutter_container_add_actor(),
* clutter_container_lower_child() and clutter_layout_manager_child_set()
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_insert_child_below() instead.
* To set specific layout properties, use clutter_layout_manager_child_set()
*/
void
clutter_box_pack_before (ClutterBox *box,
ClutterActor *actor,
ClutterActor *sibling,
const gchar *first_property,
...)
{
va_list var_args;
g_return_if_fail (CLUTTER_IS_BOX (box));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling));
clutter_container_add_actor (CLUTTER_CONTAINER (box), actor);
clutter_container_lower_child (CLUTTER_CONTAINER (box), actor, sibling);
if (first_property == NULL || *first_property == '\0')
return;
va_start (var_args, first_property);
clutter_box_set_property_valist (box, actor, first_property, var_args);
va_end (var_args);
}
/**
* clutter_box_pack_at:
* @box: a #ClutterBox
* @actor: a #ClutterActor
* @position: the position to insert the @actor at
* @first_property: the name of the first property to set, or %NULL
* @...: a list of property name and value pairs, terminated by %NULL
*
* Adds @actor to @box, placing it at @position, and sets layout
* properties at the same time, if the #ClutterLayoutManager used by
* @box supports them
*
* If @position is a negative number, or is larger than the number of
* children of @box, the new child is added at the end of the list of
* children
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_insert_child_at_index() instead.
* To set specific layout properties, use clutter_layout_manager_child_set()
*/
void
clutter_box_pack_at (ClutterBox *box,
ClutterActor *actor,
gint position,
const gchar *first_property,
...)
{
va_list var_args;
g_return_if_fail (CLUTTER_IS_BOX (box));
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
clutter_actor_insert_child_at_index (CLUTTER_ACTOR (box),
actor,
position);
/* we need to explicitly call this, because we're not going through
* the default code paths provided by clutter_container_add()
*/
clutter_container_create_child_meta (CLUTTER_CONTAINER (box), actor);
g_signal_emit_by_name (box, "actor-added", actor);
if (first_property == NULL || *first_property == '\0')
return;
va_start (var_args, first_property);
clutter_box_set_property_valist (box, actor, first_property, var_args);
va_end (var_args);
}
/**
* clutter_box_set_color:
* @box: a #ClutterBox
* @color: (allow-none): the background color, or %NULL to unset
*
* Sets (or unsets) the background color for @box
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_set_background_color() instead.
*/
void
clutter_box_set_color (ClutterBox *box,
const ClutterColor *color)
{
g_return_if_fail (CLUTTER_IS_BOX (box));
clutter_box_set_color_internal (box, color);
}
/**
* clutter_box_get_color:
* @box: a #ClutterBox
* @color: (out caller-allocates): return location for a #ClutterColor
*
* Retrieves the background color of @box
*
* If the #ClutterBox:color-set property is set to %FALSE the
* returned #ClutterColor is undefined
*
* Since: 1.2
*
* Deprecated: 1.10: Use clutter_actor_get_background_color() instead.
*/
void
clutter_box_get_color (ClutterBox *box,
ClutterColor *color)
{
g_return_if_fail (CLUTTER_IS_BOX (box));
g_return_if_fail (color != NULL);
clutter_actor_get_background_color (CLUTTER_ACTOR (box), color);
}

View File

@@ -1,143 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2009,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>
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_BOX_H__
#define __CLUTTER_BOX_H__
#include <clutter/clutter-actor.h>
#include <clutter/clutter-container.h>
#include <clutter/clutter-layout-manager.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BOX (clutter_box_get_type ())
#define CLUTTER_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX, ClutterBox))
#define CLUTTER_IS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX))
#define CLUTTER_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX, ClutterBoxClass))
#define CLUTTER_IS_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX))
#define CLUTTER_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX, ClutterBoxClass))
typedef struct _ClutterBox ClutterBox;
typedef struct _ClutterBoxPrivate ClutterBoxPrivate;
typedef struct _ClutterBoxClass ClutterBoxClass;
/**
* ClutterBox:
*
* The #ClutterBox structure contains only private data and should
* be accessed using the provided API
*
* Since: 1.2
*/
struct _ClutterBox
{
/*< private >*/
ClutterActor parent_instance;
ClutterBoxPrivate *priv;
};
/**
* ClutterBoxClass:
*
* The #ClutterBoxClass structure contains only private data
*
* Since: 1.2
*/
struct _ClutterBoxClass
{
/*< private >*/
ClutterActorClass parent_class;
/* padding, for future expansion */
void (*clutter_padding_1) (void);
void (*clutter_padding_2) (void);
void (*clutter_padding_3) (void);
void (*clutter_padding_4) (void);
void (*clutter_padding_5) (void);
void (*clutter_padding_6) (void);
};
CLUTTER_DEPRECATED
GType clutter_box_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
ClutterActor * clutter_box_new (ClutterLayoutManager *manager);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_layout_manager)
void clutter_box_set_layout_manager (ClutterBox *box,
ClutterLayoutManager *manager);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_layout_manager)
ClutterLayoutManager *clutter_box_get_layout_manager (ClutterBox *box);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
void clutter_box_set_color (ClutterBox *box,
const ClutterColor *color);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color)
void clutter_box_get_color (ClutterBox *box,
ClutterColor *color);
CLUTTER_DEPRECATED_FOR(clutter_actor_add_child)
void clutter_box_pack (ClutterBox *box,
ClutterActor *actor,
const gchar *first_property,
...);
CLUTTER_DEPRECATED_FOR(clutter_actor_add_child)
void clutter_box_packv (ClutterBox *box,
ClutterActor *actor,
guint n_properties,
const gchar * const properties[],
const GValue *values);
CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_above)
void clutter_box_pack_after (ClutterBox *box,
ClutterActor *actor,
ClutterActor *sibling,
const gchar *first_property,
...);
CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_below)
void clutter_box_pack_before (ClutterBox *box,
ClutterActor *actor,
ClutterActor *sibling,
const gchar *first_property,
...);
CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_at_index)
void clutter_box_pack_at (ClutterBox *box,
ClutterActor *actor,
gint position,
const gchar *first_property,
...);
G_END_DECLS
#endif /* __CLUTTER_BOX_H__ */

View File

@@ -1,554 +0,0 @@
/*
* 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/>.
*/
/**
* SECTION:clutter-group
* @short_description: A fixed layout container
*
* A #ClutterGroup is an Actor which contains multiple child actors positioned
* relative to the #ClutterGroup position. Other operations such as scaling,
* rotating and clipping of the group will apply to the child actors.
*
* A #ClutterGroup's size is defined by the size and position of its children;
* it will be the smallest non-negative size that covers the right and bottom
* edges of all of its children.
*
* Setting the size on a Group using #ClutterActor methods like
* clutter_actor_set_size() will override the natural size of the Group,
* however this will not affect the size of the children and they may still
* be painted outside of the allocation of the group. One way to constrain
* the visible area of a #ClutterGroup to a specified allocation is to
* explicitly set the size of the #ClutterGroup and then use the
* #ClutterActor:clip-to-allocation property.
*
* #ClutterGroup as a concrete class has been superceded by #ClutterActor
* since Clutter 1.10. The type itself is not deprecated as it is used by
* #ClutterStage. You should instantiate #ClutterActor and use its API to
* manage child actors.
*/
#include "clutter-build-config.h"
#include <stdarg.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-group.h"
#include "clutter-actor.h"
#include "clutter-actor-private.h"
#include "clutter-container.h"
#include "clutter-fixed-layout.h"
#include "clutter-main.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "cogl/cogl.h"
struct _ClutterGroupPrivate
{
GList *children;
ClutterLayoutManager *layout;
};
static void clutter_container_iface_init (ClutterContainerIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterGroup, clutter_group, CLUTTER_TYPE_ACTOR,
G_ADD_PRIVATE (ClutterGroup)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
clutter_container_iface_init));
static gint
sort_by_depth (gconstpointer a,
gconstpointer b)
{
gfloat depth_a = clutter_actor_get_depth (CLUTTER_ACTOR(a));
gfloat depth_b = clutter_actor_get_depth (CLUTTER_ACTOR(b));
if (depth_a < depth_b)
return -1;
if (depth_a > depth_b)
return 1;
return 0;
}
static void
clutter_group_real_add (ClutterContainer *container,
ClutterActor *actor)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
g_object_ref (actor);
priv->children = g_list_append (priv->children, actor);
clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
g_signal_emit_by_name (container, "actor-added", actor);
clutter_container_sort_depth_order (container);
g_object_unref (actor);
}
static void
clutter_group_real_actor_added (ClutterContainer *container,
ClutterActor *actor)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
/* XXX - children added using clutter_actor_add_child() will
* cause actor-added to be emitted without going through the
* add() virtual function.
*
* if we get an actor-added for a child that is not in our
* list of children already, then we go in compatibility
* mode.
*/
if (g_list_find (priv->children, actor) != NULL)
return;
priv->children = g_list_append (priv->children, actor);
clutter_container_sort_depth_order (container);
}
static void
clutter_group_real_remove (ClutterContainer *container,
ClutterActor *actor)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
g_object_ref (actor);
priv->children = g_list_remove (priv->children, actor);
clutter_actor_unparent (actor);
clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
g_signal_emit_by_name (container, "actor-removed", actor);
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
g_object_unref (actor);
}
static void
clutter_group_real_actor_removed (ClutterContainer *container,
ClutterActor *actor)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
/* XXX - same compatibility mode of the ::actor-added implementation */
if (g_list_find (priv->children, actor) == NULL)
return;
priv->children = g_list_remove (priv->children, actor);
}
static void
clutter_group_real_raise (ClutterContainer *container,
ClutterActor *actor,
ClutterActor *sibling)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
priv->children = g_list_remove (priv->children, actor);
/* Raise at the top */
if (!sibling)
{
GList *last_item;
last_item = g_list_last (priv->children);
if (last_item)
sibling = last_item->data;
priv->children = g_list_append (priv->children, actor);
}
else
{
gint index_ = g_list_index (priv->children, sibling) + 1;
priv->children = g_list_insert (priv->children, actor, index_);
}
/* set Z ordering a value below, this will then call sort
* as values are equal ordering shouldn't change but Z
* values will be correct.
*
* FIXME: get rid of this crap; this is so utterly broken and wrong on
* so many levels it's not even funny. sadly, we get to keep this until
* we can break API and remove Group for good.
*/
if (sibling &&
clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor))
{
clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling));
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
}
static void
clutter_group_real_lower (ClutterContainer *container,
ClutterActor *actor,
ClutterActor *sibling)
{
ClutterGroup *self = CLUTTER_GROUP (container);
ClutterGroupPrivate *priv = self->priv;
priv->children = g_list_remove (priv->children, actor);
/* Push to bottom */
if (!sibling)
{
GList *last_item;
last_item = g_list_first (priv->children);
if (last_item)
sibling = last_item->data;
priv->children = g_list_prepend (priv->children, actor);
}
else
{
gint index_ = g_list_index (priv->children, sibling);
priv->children = g_list_insert (priv->children, actor, index_);
}
/* See comment in group_raise for this */
if (sibling &&
clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor))
{
clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling));
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
}
static void
clutter_group_real_sort_depth_order (ClutterContainer *container)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
priv->children = g_list_sort (priv->children, sort_by_depth);
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
}
static void
clutter_container_iface_init (ClutterContainerIface *iface)
{
iface->add = clutter_group_real_add;
iface->actor_added = clutter_group_real_actor_added;
iface->remove = clutter_group_real_remove;
iface->actor_removed = clutter_group_real_actor_removed;
iface->raise = clutter_group_real_raise;
iface->lower = clutter_group_real_lower;
iface->sort_depth_order = clutter_group_real_sort_depth_order;
}
static void
clutter_group_real_paint (ClutterActor *actor,
ClutterPaintContext *paint_context)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
CLUTTER_NOTE (PAINT, "ClutterGroup paint enter '%s'",
_clutter_actor_get_debug_name (actor));
g_list_foreach (priv->children, (GFunc) clutter_actor_paint, paint_context);
CLUTTER_NOTE (PAINT, "ClutterGroup paint leave '%s'",
_clutter_actor_get_debug_name (actor));
}
static void
clutter_group_real_pick (ClutterActor *actor,
ClutterPickContext *pick_context)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
/* Chain up so we get a bounding box pained (if we are reactive) */
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, pick_context);
g_list_foreach (priv->children, (GFunc) clutter_actor_pick, pick_context);
}
static void
clutter_group_real_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gfloat *min_width,
gfloat *natural_width)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
clutter_layout_manager_get_preferred_width (priv->layout,
CLUTTER_CONTAINER (actor),
for_height,
min_width, natural_width);
}
static void
clutter_group_real_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gfloat *min_height,
gfloat *natural_height)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
clutter_layout_manager_get_preferred_height (priv->layout,
CLUTTER_CONTAINER (actor),
for_width,
min_height, natural_height);
}
static void
clutter_group_real_allocate (ClutterActor *actor,
const ClutterActorBox *allocation)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
ClutterActorClass *klass;
klass = CLUTTER_ACTOR_CLASS (clutter_group_parent_class);
klass->allocate (actor, allocation);
if (priv->children == NULL)
return;
clutter_layout_manager_allocate (priv->layout,
CLUTTER_CONTAINER (actor),
allocation);
}
static void
clutter_group_dispose (GObject *object)
{
ClutterGroup *self = CLUTTER_GROUP (object);
ClutterGroupPrivate *priv = self->priv;
/* Note: we are careful to consider that destroying children could
* have the side-effect of destroying other children so
* priv->children may be modified during clutter_actor_destroy. */
while (priv->children != NULL)
{
ClutterActor *child = priv->children->data;
priv->children = g_list_delete_link (priv->children, priv->children);
clutter_actor_destroy (child);
}
if (priv->layout)
{
clutter_layout_manager_set_container (priv->layout, NULL);
g_object_unref (priv->layout);
priv->layout = NULL;
}
G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object);
}
static void
clutter_group_real_show_all (ClutterActor *self)
{
ClutterActorIter iter;
ClutterActor *actor;
clutter_actor_iter_init (&iter, self);
while (clutter_actor_iter_next (&iter, &actor))
clutter_actor_show (actor);
clutter_actor_show (self);
}
static void
clutter_group_real_hide_all (ClutterActor *actor)
{
ClutterActorIter iter;
clutter_actor_hide (actor);
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &actor))
clutter_actor_hide (actor);
}
static gboolean
clutter_group_real_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
GList *l;
if (priv->children == NULL)
return TRUE;
for (l = priv->children; l != NULL; l = l->next)
{
ClutterActor *child = l->data;
const ClutterPaintVolume *child_volume;
/* This gets the paint volume of the child transformed into the
* group's coordinate space... */
child_volume = clutter_actor_get_transformed_paint_volume (child, actor);
if (!child_volume)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
return TRUE;
}
static void
clutter_group_class_init (ClutterGroupClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->get_preferred_width = clutter_group_real_get_preferred_width;
actor_class->get_preferred_height = clutter_group_real_get_preferred_height;
actor_class->allocate = clutter_group_real_allocate;
actor_class->paint = clutter_group_real_paint;
actor_class->pick = clutter_group_real_pick;
actor_class->show_all = clutter_group_real_show_all;
actor_class->hide_all = clutter_group_real_hide_all;
actor_class->get_paint_volume = clutter_group_real_get_paint_volume;
gobject_class->dispose = clutter_group_dispose;
}
static void
clutter_group_init (ClutterGroup *self)
{
ClutterActor *actor = CLUTTER_ACTOR (self);
self->priv = clutter_group_get_instance_private (self);
/* turn on some optimization
*
* XXX - these so-called "optimizations" are insane and should have never
* been used. they introduce some weird behaviour that breaks invariants
* and have to be explicitly worked around.
*
* this flag was set by the ClutterFixedLayout, but since that layout
* manager is now the default for ClutterActor, we set the flag explicitly
* here, to avoid breaking perfectly working actors overriding the
* allocate() virtual function.
*
* also, we keep this flag here so that it can die once we get rid of
* ClutterGroup.
*/
clutter_actor_set_flags (actor, CLUTTER_ACTOR_NO_LAYOUT);
self->priv->layout = clutter_fixed_layout_new ();
g_object_ref_sink (self->priv->layout);
clutter_actor_set_layout_manager (actor, self->priv->layout);
}
/**
* clutter_group_new:
*
* Create a new #ClutterGroup.
*
* Return value: the newly created #ClutterGroup actor
*
* Deprecated: 1.10: Use clutter_actor_new() instead.
*/
ClutterActor *
clutter_group_new (void)
{
return g_object_new (CLUTTER_TYPE_GROUP, NULL);
}
/**
* clutter_group_remove_all:
* @self: A #ClutterGroup
*
* Removes all children actors from the #ClutterGroup.
*
* Deprecated: 1.10: Use clutter_actor_remove_all_children() instead.
*/
void
clutter_group_remove_all (ClutterGroup *self)
{
g_return_if_fail (CLUTTER_IS_GROUP (self));
clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
}
/**
* clutter_group_get_n_children:
* @self: A #ClutterGroup
*
* Gets the number of actors held in the group.
*
* Return value: The number of child actors held in the group.
*
* Since: 0.2
*
* Deprecated: 1.10: Use clutter_actor_get_n_children() instead.
*/
gint
clutter_group_get_n_children (ClutterGroup *self)
{
g_return_val_if_fail (CLUTTER_IS_GROUP (self), 0);
return clutter_actor_get_n_children (CLUTTER_ACTOR (self));
}
/**
* clutter_group_get_nth_child:
* @self: A #ClutterGroup
* @index_: the position of the requested actor.
*
* Gets a groups child held at @index_ in stack.
*
* Return value: (transfer none): A Clutter actor, or %NULL if
* @index_ is invalid.
*
* Since: 0.2
*
* Deprecated: 1.10: Use clutter_actor_get_child_at_index() instead.
*/
ClutterActor *
clutter_group_get_nth_child (ClutterGroup *self,
gint index_)
{
ClutterActor *actor;
g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL);
actor = CLUTTER_ACTOR (self);
g_return_val_if_fail (index_ <= clutter_actor_get_n_children (actor), NULL);
return clutter_actor_get_child_at_index (actor, index_);
}

View File

@@ -1,62 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2011 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_GROUP_DEPRECATED_H__
#define __CLUTTER_GROUP_DEPRECATED_H__
#include <clutter/clutter-types.h>
#include <clutter/clutter-group.h>
G_BEGIN_DECLS
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
ClutterActor * clutter_group_new (void);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_child_at_index)
ClutterActor * clutter_group_get_nth_child (ClutterGroup *self,
gint index_);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_n_children)
gint clutter_group_get_n_children (ClutterGroup *self);
CLUTTER_DEPRECATED_FOR(clutter_actor_remove_all_children)
void clutter_group_remove_all (ClutterGroup *self);
#ifndef CLUTTER_DISABLE_DEPRECATED
/* for Mr. Mallum only */
#define clutter_group_add(group,actor) G_STMT_START { \
ClutterActor *_actor = (ClutterActor *) (actor); \
if (CLUTTER_IS_GROUP ((group)) && CLUTTER_IS_ACTOR ((_actor))) \
{ \
ClutterContainer *_container = (ClutterContainer *) (group); \
clutter_container_add_actor (_container, _actor); \
} } G_STMT_END
#endif /* CLUTTER_DISABLE_DEPRECATED */
G_END_DECLS
#endif /* __CLUTTER_GROUP_DEPRECATED_H__ */

View File

@@ -1,626 +0,0 @@
/*
* 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/>.
*
*
*/
/**
* SECTION:clutter-rectangle
* @short_description: An actor that displays a simple rectangle.
*
* #ClutterRectangle is a #ClutterActor which draws a simple filled rectangle.
*
* #ClutterRectangle is deprecated since Clutter 1.10. If you want an actor
* painting a solid color, you can replace it with #ClutterActor and set the
* #ClutterActor:background-color property to the desired #ClutterColor. If
* you are drawing more complex shapes, use #ClutterCanvas to draw using the
* Cairo 2D API instead.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-rectangle.h"
#include "deprecated/clutter-actor.h"
#include "clutter-actor-private.h"
#include "clutter-color.h"
#include "clutter-debug.h"
#include "clutter-main.h"
#include "clutter-private.h"
#include "cogl/cogl.h"
struct _ClutterRectanglePrivate
{
ClutterColor color;
ClutterColor border_color;
guint border_width;
guint has_border : 1;
};
enum
{
PROP_0,
PROP_COLOR,
PROP_BORDER_COLOR,
PROP_BORDER_WIDTH,
PROP_HAS_BORDER
/* FIXME: Add gradient, rounded corner props etc */
};
static const ClutterColor default_color = { 255, 255, 255, 255 };
static const ClutterColor default_border_color = { 0, 0, 0, 255 };
G_DEFINE_TYPE_WITH_PRIVATE (ClutterRectangle, clutter_rectangle, CLUTTER_TYPE_ACTOR)
static void
clutter_rectangle_paint (ClutterActor *self,
ClutterPaintContext *paint_context)
{
ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE (self)->priv;
CoglFramebuffer *framebuffer =
clutter_paint_context_get_framebuffer (paint_context);
static CoglPipeline *default_color_pipeline = NULL;
CoglPipeline *content_pipeline;
ClutterActorBox alloc;
CoglColor color;
guint8 tmp_alpha;
CLUTTER_NOTE (PAINT,
"painting rect '%s'",
clutter_actor_get_name (self) ? clutter_actor_get_name (self)
: "unknown");
clutter_actor_get_allocation_box (self, &alloc);
if (G_UNLIKELY (default_color_pipeline == NULL))
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
default_color_pipeline = cogl_pipeline_new (ctx);
}
g_assert (default_color_pipeline != NULL);
content_pipeline = cogl_pipeline_copy (default_color_pipeline);
/* compute the composited opacity of the actor taking into
* account the opacity of the color set by the user
*/
tmp_alpha = clutter_actor_get_paint_opacity (self)
* priv->color.alpha
/ 255;
cogl_color_init_from_4ub (&color,
priv->color.red,
priv->color.green,
priv->color.blue,
tmp_alpha);
cogl_color_premultiply (&color);
cogl_pipeline_set_color (content_pipeline, &color);
if (priv->has_border)
{
CoglPipeline *border_pipeline;
border_pipeline = cogl_pipeline_copy (default_color_pipeline);
tmp_alpha = clutter_actor_get_paint_opacity (self)
* priv->border_color.alpha
/ 255;
cogl_color_init_from_4ub (&color,
priv->border_color.red,
priv->border_color.green,
priv->border_color.blue,
tmp_alpha);
cogl_color_premultiply (&color);
cogl_pipeline_set_color (border_pipeline, &color);
/* We paint the border and the content only if the rectangle
* is big enough to show them
*/
if ((priv->border_width * 2) < clutter_actor_box_get_width (&alloc) &&
(priv->border_width * 2) < clutter_actor_box_get_height (&alloc))
{
/* paint the border. this sucks, but it's the only way to make a border */
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
priv->border_width, 0,
clutter_actor_box_get_width (&alloc),
priv->border_width);
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
clutter_actor_box_get_width (&alloc) - priv->border_width,
priv->border_width,
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
0, clutter_actor_box_get_height (&alloc) - priv->border_width,
clutter_actor_box_get_width (&alloc) - priv->border_width,
clutter_actor_box_get_height (&alloc));
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
0, 0,
priv->border_width,
clutter_actor_box_get_height (&alloc) - priv->border_width);
/* now paint the rectangle */
cogl_framebuffer_draw_rectangle (framebuffer,
content_pipeline,
priv->border_width, priv->border_width,
clutter_actor_box_get_width (&alloc) - priv->border_width,
clutter_actor_box_get_height (&alloc) - priv->border_width);
}
else
{
/* Otherwise, we draw a rectangle with the same color
* as the border, since we can only fit that into the
* allocation.
*/
cogl_framebuffer_draw_rectangle (framebuffer,
border_pipeline,
0, 0,
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
}
cogl_object_unref (border_pipeline);
}
else
{
cogl_framebuffer_draw_rectangle (framebuffer,
content_pipeline,
0, 0,
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
}
cogl_object_unref (content_pipeline);
}
static gboolean
clutter_rectangle_get_paint_volume (ClutterActor *self,
ClutterPaintVolume *volume)
{
return _clutter_actor_set_default_paint_volume (self,
CLUTTER_TYPE_RECTANGLE,
volume);
}
static gboolean
clutter_rectangle_has_overlaps (ClutterActor *self)
{
/* Rectangles never need an offscreen redirect because there are
never any overlapping primitives */
return FALSE;
}
static void
clutter_rectangle_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterRectangle *rectangle = CLUTTER_RECTANGLE(object);
switch (prop_id)
{
case PROP_COLOR:
clutter_rectangle_set_color (rectangle, clutter_value_get_color (value));
break;
case PROP_BORDER_COLOR:
clutter_rectangle_set_border_color (rectangle,
clutter_value_get_color (value));
break;
case PROP_BORDER_WIDTH:
clutter_rectangle_set_border_width (rectangle,
g_value_get_uint (value));
break;
case PROP_HAS_BORDER:
rectangle->priv->has_border = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_rectangle_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE(object)->priv;
switch (prop_id)
{
case PROP_COLOR:
clutter_value_set_color (value, &priv->color);
break;
case PROP_BORDER_COLOR:
clutter_value_set_color (value, &priv->border_color);
break;
case PROP_BORDER_WIDTH:
g_value_set_uint (value, priv->border_width);
break;
case PROP_HAS_BORDER:
g_value_set_boolean (value, priv->has_border);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_rectangle_finalize (GObject *object)
{
G_OBJECT_CLASS (clutter_rectangle_parent_class)->finalize (object);
}
static void
clutter_rectangle_dispose (GObject *object)
{
G_OBJECT_CLASS (clutter_rectangle_parent_class)->dispose (object);
}
static void
clutter_rectangle_class_init (ClutterRectangleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GParamSpec *pspec;
actor_class->paint = clutter_rectangle_paint;
actor_class->get_paint_volume = clutter_rectangle_get_paint_volume;
actor_class->has_overlaps = clutter_rectangle_has_overlaps;
gobject_class->finalize = clutter_rectangle_finalize;
gobject_class->dispose = clutter_rectangle_dispose;
gobject_class->set_property = clutter_rectangle_set_property;
gobject_class->get_property = clutter_rectangle_get_property;
/**
* ClutterRectangle:color:
*
* The color of the rectangle.
*/
pspec = clutter_param_spec_color ("color",
P_("Color"),
P_("The color of the rectangle"),
&default_color,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_COLOR, pspec);
/**
* ClutterRectangle:border-color:
*
* The color of the border of the rectangle.
*
* Since: 0.2
*/
pspec = clutter_param_spec_color ("border-color",
P_("Border Color"),
P_("The color of the border of the rectangle"),
&default_border_color,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_BORDER_COLOR, pspec);
/**
* ClutterRectangle:border-width:
*
* The width of the border of the rectangle, in pixels.
*
* Since: 0.2
*/
g_object_class_install_property (gobject_class,
PROP_BORDER_WIDTH,
g_param_spec_uint ("border-width",
P_("Border Width"),
P_("The width of the border of the rectangle"),
0, G_MAXUINT,
0,
CLUTTER_PARAM_READWRITE));
/**
* ClutterRectangle:has-border:
*
* Whether the #ClutterRectangle should be displayed with a border.
*
* Since: 0.2
*/
g_object_class_install_property (gobject_class,
PROP_HAS_BORDER,
g_param_spec_boolean ("has-border",
P_("Has Border"),
P_("Whether the rectangle should have a border"),
FALSE,
CLUTTER_PARAM_READWRITE));
}
static void
clutter_rectangle_init (ClutterRectangle *self)
{
ClutterRectanglePrivate *priv;
self->priv = priv = clutter_rectangle_get_instance_private (self);
priv->color = default_color;
priv->border_color = default_border_color;
priv->border_width = 0;
priv->has_border = FALSE;
}
/**
* clutter_rectangle_new:
*
* Creates a new #ClutterActor with a rectangular shape.
*
* Return value: a new #ClutterRectangle
*
* Deprecated: 1.10: Use clutter_actor_new() instead
*/
ClutterActor*
clutter_rectangle_new (void)
{
return g_object_new (CLUTTER_TYPE_RECTANGLE, NULL);
}
/**
* clutter_rectangle_new_with_color:
* @color: a #ClutterColor
*
* Creates a new #ClutterActor with a rectangular shape
* and of the given @color.
*
* Return value: a new #ClutterRectangle
*
* Deprecated: 1.10: Use clutter_actor_new() and
* clutter_actor_set_background_color() instead
*/
ClutterActor *
clutter_rectangle_new_with_color (const ClutterColor *color)
{
return g_object_new (CLUTTER_TYPE_RECTANGLE,
"color", color,
NULL);
}
/**
* clutter_rectangle_get_color:
* @rectangle: a #ClutterRectangle
* @color: (out caller-allocates): return location for a #ClutterColor
*
* Retrieves the color of @rectangle.
*
* Deprecated: 1.10: Use #ClutterActor and clutter_actor_get_background_color()
* instead
*/
void
clutter_rectangle_get_color (ClutterRectangle *rectangle,
ClutterColor *color)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
priv = rectangle->priv;
color->red = priv->color.red;
color->green = priv->color.green;
color->blue = priv->color.blue;
color->alpha = priv->color.alpha;
}
/**
* clutter_rectangle_set_color:
* @rectangle: a #ClutterRectangle
* @color: a #ClutterColor
*
* Sets the color of @rectangle.
*
* Deprecated: 1.10: Use #ClutterActor and clutter_actor_set_background_color()
* instead
*/
void
clutter_rectangle_set_color (ClutterRectangle *rectangle,
const ClutterColor *color)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
g_object_ref (rectangle);
priv = rectangle->priv;
priv->color.red = color->red;
priv->color.green = color->green;
priv->color.blue = color->blue;
priv->color.alpha = color->alpha;
#if 0
/* FIXME - appears to be causing border to always get drawn */
if (clutter_color_equal (&priv->color, &priv->border_color))
priv->has_border = FALSE;
else
priv->has_border = TRUE;
#endif
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
g_object_notify (G_OBJECT (rectangle), "color");
g_object_notify (G_OBJECT (rectangle), "has-border");
g_object_unref (rectangle);
}
/**
* clutter_rectangle_get_border_width:
* @rectangle: a #ClutterRectangle
*
* Gets the width (in pixels) of the border used by @rectangle
*
* Return value: the border's width
*
* Since: 0.2
*
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content
* to draw the border using Cairo
*/
guint
clutter_rectangle_get_border_width (ClutterRectangle *rectangle)
{
g_return_val_if_fail (CLUTTER_IS_RECTANGLE (rectangle), 0);
return rectangle->priv->border_width;
}
/**
* clutter_rectangle_set_border_width:
* @rectangle: a #ClutterRectangle
* @width: the width of the border
*
* Sets the width (in pixel) of the border used by @rectangle.
* A @width of 0 will unset the border.
*
* Since: 0.2
*
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content
* to draw the border using Cairo
*/
void
clutter_rectangle_set_border_width (ClutterRectangle *rectangle,
guint width)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
priv = rectangle->priv;
if (priv->border_width != width)
{
g_object_ref (rectangle);
priv->border_width = width;
if (priv->border_width != 0)
priv->has_border = TRUE;
else
priv->has_border = FALSE;
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
g_object_notify (G_OBJECT (rectangle), "border-width");
g_object_notify (G_OBJECT (rectangle), "has-border");
g_object_unref (rectangle);
}
}
/**
* clutter_rectangle_get_border_color:
* @rectangle: a #ClutterRectangle
* @color: (out caller-allocates): return location for a #ClutterColor
*
* Gets the color of the border used by @rectangle and places
* it into @color.
*
* Since: 0.2
*
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw
* the border with Cairo
*/
void
clutter_rectangle_get_border_color (ClutterRectangle *rectangle,
ClutterColor *color)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
priv = rectangle->priv;
color->red = priv->border_color.red;
color->green = priv->border_color.green;
color->blue = priv->border_color.blue;
color->alpha = priv->border_color.alpha;
}
/**
* clutter_rectangle_set_border_color:
* @rectangle: a #ClutterRectangle
* @color: the color of the border
*
* Sets the color of the border used by @rectangle using @color
*
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw
* the border with Cairo
*/
void
clutter_rectangle_set_border_color (ClutterRectangle *rectangle,
const ClutterColor *color)
{
ClutterRectanglePrivate *priv;
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
g_return_if_fail (color != NULL);
priv = rectangle->priv;
if (priv->border_color.red != color->red ||
priv->border_color.green != color->green ||
priv->border_color.blue != color->blue ||
priv->border_color.alpha != color->alpha)
{
g_object_ref (rectangle);
priv->border_color.red = color->red;
priv->border_color.green = color->green;
priv->border_color.blue = color->blue;
priv->border_color.alpha = color->alpha;
if (clutter_color_equal (&priv->color, &priv->border_color))
priv->has_border = FALSE;
else
priv->has_border = TRUE;
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
g_object_notify (G_OBJECT (rectangle), "border-color");
g_object_notify (G_OBJECT (rectangle), "has-border");
g_object_unref (rectangle);
}
}

View File

@@ -1,117 +0,0 @@
/*
* 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/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_RECTANGLE_H__
#define __CLUTTER_RECTANGLE_H__
#include <glib-object.h>
#include <clutter/clutter-actor.h>
#include <clutter/clutter-color.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_RECTANGLE (clutter_rectangle_get_type())
#define CLUTTER_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangle))
#define CLUTTER_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass))
#define CLUTTER_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_RECTANGLE))
#define CLUTTER_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_RECTANGLE))
#define CLUTTER_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass))
typedef struct _ClutterRectangle ClutterRectangle;
typedef struct _ClutterRectangleClass ClutterRectangleClass;
typedef struct _ClutterRectanglePrivate ClutterRectanglePrivate;
/**
* ClutterRectangle:
*
* The #ClutterRectangle structure contains only private data
* and should be accessed using the provided API
*
* Since: 0.2
*/
struct _ClutterRectangle
{
/*< private >*/
ClutterActor parent;
ClutterRectanglePrivate *priv;
};
/**
* ClutterRectangleClass:
*
* The #ClutterRectangleClass structure contains only private data
*
* Since: 0.2
*/
struct _ClutterRectangleClass
{
/*< private >*/
ClutterActorClass parent_class;
/* padding for future expansion */
void (*_clutter_rectangle1) (void);
void (*_clutter_rectangle2) (void);
void (*_clutter_rectangle3) (void);
void (*_clutter_rectangle4) (void);
};
CLUTTER_DEPRECATED
GType clutter_rectangle_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
ClutterActor *clutter_rectangle_new (void);
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
ClutterActor *clutter_rectangle_new_with_color (const ClutterColor *color);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color)
void clutter_rectangle_get_color (ClutterRectangle *rectangle,
ClutterColor *color);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
void clutter_rectangle_set_color (ClutterRectangle *rectangle,
const ClutterColor *color);
CLUTTER_DEPRECATED
guint clutter_rectangle_get_border_width (ClutterRectangle *rectangle);
CLUTTER_DEPRECATED
void clutter_rectangle_set_border_width (ClutterRectangle *rectangle,
guint width);
CLUTTER_DEPRECATED
void clutter_rectangle_get_border_color (ClutterRectangle *rectangle,
ClutterColor *color);
CLUTTER_DEPRECATED
void clutter_rectangle_set_border_color (ClutterRectangle *rectangle,
const ClutterColor *color);
G_END_DECLS
#endif /* __CLUTTER_RECTANGLE_H__ */

View File

@@ -1,91 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2011 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_STAGE_DEPRECATED_H__
#define __CLUTTER_STAGE_DEPRECATED_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#ifndef CLUTTER_DISABLE_DEPRECATED
/**
* CLUTTER_STAGE_WIDTH:
*
* Macro that evaluates to the width of the default stage
*
* Since: 0.2
*
* Deprecated: 1.2: Use clutter_actor_get_width() instead
*/
#define CLUTTER_STAGE_WIDTH() (clutter_actor_get_width (clutter_stage_get_default ()))
/**
* CLUTTER_STAGE_HEIGHT:
*
* Macro that evaluates to the height of the default stage
*
* Since: 0.2
*
* Deprecated: 1.2: use clutter_actor_get_height() instead
*/
#define CLUTTER_STAGE_HEIGHT() (clutter_actor_get_height (clutter_stage_get_default ()))
/* Commodity macro, for mallum only */
#define clutter_stage_add(stage,actor) G_STMT_START { \
if (CLUTTER_IS_STAGE ((stage)) && CLUTTER_IS_ACTOR ((actor))) \
{ \
ClutterContainer *_container = (ClutterContainer *) (stage); \
ClutterActor *_actor = (ClutterActor *) (actor); \
clutter_container_add_actor (_container, _actor); \
} } G_STMT_END
#endif /* CLUTTER_DISABLE_DEPRECATED */
CLUTTER_DEPRECATED_FOR(clutter_stage_new)
ClutterActor * clutter_stage_get_default (void);
CLUTTER_DEPRECATED
gboolean clutter_stage_is_default (ClutterStage *stage);
CLUTTER_DEPRECATED_FOR(clutter_actor_queue_redraw)
void clutter_stage_queue_redraw (ClutterStage *stage);
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
void clutter_stage_set_color (ClutterStage *stage,
const ClutterColor *color);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color)
void clutter_stage_get_color (ClutterStage *stage,
ClutterColor *color);
CLUTTER_DEPRECATED
void clutter_stage_ensure_current (ClutterStage *stage);
G_END_DECLS
#endif /* __CLUTTER_STAGE_DEPRECATED_H__ */

View File

@@ -26,6 +26,9 @@
G_BEGIN_DECLS
CLUTTER_DEPRECATED_FOR(clutter_timeline_new_for_actor)
ClutterTimeline * clutter_timeline_new (guint duration_ms);
G_END_DECLS
#endif /* __CLUTTER_TIMELINE_PRIVATE_H__ */

View File

@@ -36,9 +36,9 @@ clutter_headers = [
'clutter-feature.h',
'clutter-fixed-layout.h',
'clutter-flow-layout.h',
'clutter-frame-clock.h',
'clutter-gesture-action.h',
'clutter-grid-layout.h',
'clutter-group.h',
'clutter-image.h',
'clutter-input-device.h',
'clutter-input-device-tool.h',
@@ -123,6 +123,7 @@ clutter_sources = [
'clutter-fixed-layout.c',
'clutter-flatten-effect.c',
'clutter-flow-layout.c',
'clutter-frame-clock.c',
'clutter-gesture-action.c',
'clutter-graphene.c',
'clutter-grid-layout.c',
@@ -140,8 +141,6 @@ clutter_sources = [
'clutter-layout-manager.c',
'clutter-layout-meta.c',
'clutter-main.c',
'clutter-master-clock.c',
'clutter-master-clock-default.c',
'clutter-offscreen-effect.c',
'clutter-page-turn-effect.c',
'clutter-paint-context.c',
@@ -199,8 +198,6 @@ clutter_private_headers = [
'clutter-input-focus-private.h',
'clutter-input-method-private.h',
'clutter-input-pointer-a11y-private.h',
'clutter-master-clock.h',
'clutter-master-clock-default.h',
'clutter-offscreen-effect-private.h',
'clutter-paint-context-private.h',
'clutter-paint-node-private.h',
@@ -212,6 +209,7 @@ clutter_private_headers = [
'clutter-stage-private.h',
'clutter-stage-view-private.h',
'clutter-stage-window.h',
'clutter-timeline-private.h',
]
clutter_nonintrospected_sources = [
@@ -220,21 +218,10 @@ clutter_nonintrospected_sources = [
]
clutter_deprecated_headers = [
'deprecated/clutter-actor.h',
'deprecated/clutter-box.h',
'deprecated/clutter-container.h',
'deprecated/clutter-group.h',
'deprecated/clutter-rectangle.h',
'deprecated/clutter-stage.h',
'deprecated/clutter-timeline.h',
]
clutter_deprecated_sources = [
'deprecated/clutter-box.c',
'deprecated/clutter-group.c',
'deprecated/clutter-rectangle.c',
]
clutter_backend_sources = []
clutter_backend_nonintrospected_sources = [
'cogl/clutter-stage-cogl.c',
@@ -288,10 +275,8 @@ cally_headers = [
'cally/cally-actor.h',
'cally/cally-clone.h',
'cally/cally-factory.h',
'cally/cally-group.h',
'cally/cally.h',
'cally/cally-main.h',
'cally/cally-rectangle.h',
'cally/cally-root.h',
'cally/cally-stage.h',
'cally/cally-text.h',
@@ -302,8 +287,6 @@ cally_sources = [
'cally/cally-actor.c',
'cally/cally.c',
'cally/cally-clone.c',
'cally/cally-group.c',
'cally/cally-rectangle.c',
'cally/cally-root.c',
'cally/cally-stage.c',
'cally/cally-text.c',
@@ -385,7 +368,6 @@ libmutter_clutter = shared_library(libmutter_clutter_name,
clutter_headers,
clutter_private_headers,
clutter_nonintrospected_sources,
clutter_deprecated_sources,
clutter_deprecated_headers,
clutter_backend_sources,
clutter_backend_nonintrospected_sources,
@@ -431,7 +413,6 @@ if have_introspection
clutter_built_headers,
clutter_sources,
clutter_headers,
clutter_deprecated_sources,
clutter_deprecated_headers,
],
nsversion: libmutter_api_version,

View File

@@ -8,6 +8,7 @@ clutter_c_args = [
'-DCLUTTER_SYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)),
'-DCLUTTER_COMPILATION=1',
'-DCOGL_DISABLE_DEPRECATION_WARNINGS',
'-DCOGL_ENABLE_MUTTER_API',
'-DG_LOG_DOMAIN="Clutter"',
]

View File

@@ -45,6 +45,7 @@ struct _CoglFrameInfo
int64_t global_frame_counter;
};
CoglFrameInfo *_cogl_frame_info_new (void);
COGL_EXPORT
CoglFrameInfo *cogl_frame_info_new (int64_t global_frame_counter);
#endif /* __COGL_FRAME_INFO_PRIVATE_H */

View File

@@ -39,11 +39,12 @@ COGL_OBJECT_DEFINE (FrameInfo, frame_info);
COGL_GTYPE_DEFINE_CLASS (FrameInfo, frame_info);
CoglFrameInfo *
_cogl_frame_info_new (void)
cogl_frame_info_new (int64_t global_frame_counter)
{
CoglFrameInfo *info;
info = g_slice_new0 (CoglFrameInfo);
info->global_frame_counter = global_frame_counter;
return _cogl_frame_info_object_new (info);
}

View File

@@ -45,6 +45,11 @@
G_BEGIN_DECLS
/**
* CoglFrameInfo:
*
* Frame information.
*/
typedef struct _CoglFrameInfo CoglFrameInfo;
#define COGL_FRAME_INFO(X) ((CoglFrameInfo *)(X))

View File

@@ -293,15 +293,14 @@ _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
void
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
int n_rectangles,
CoglFrameInfo *info)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys;
CoglFrameInfo *info;
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
info = _cogl_frame_info_new ();
info->frame_counter = onscreen->frame_counter;
g_queue_push_tail (&onscreen->pending_frame_infos, info);
@@ -310,7 +309,8 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
winsys = _cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_swap_buffers_with_damage (onscreen,
rectangles, n_rectangles);
rectangles, n_rectangles,
info);
cogl_framebuffer_discard_buffers (framebuffer,
COGL_BUFFER_BIT_COLOR |
COGL_BUFFER_BIT_DEPTH |
@@ -334,23 +334,23 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
}
void
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
CoglFrameInfo *info)
{
cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0);
cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0, info);
}
void
cogl_onscreen_swap_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
int n_rectangles,
CoglFrameInfo *info)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys;
CoglFrameInfo *info;
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
info = _cogl_frame_info_new ();
info->frame_counter = onscreen->frame_counter;
g_queue_push_tail (&onscreen->pending_frame_infos, info);
@@ -365,7 +365,8 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
rectangles,
n_rectangles);
n_rectangles,
info);
cogl_framebuffer_discard_buffers (framebuffer,
COGL_BUFFER_BIT_COLOR |
@@ -406,22 +407,21 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
}
void
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout)
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout,
CoglFrameInfo *info)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys;
CoglFrameInfo *info;
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT));
info = _cogl_frame_info_new ();
info->frame_counter = onscreen->frame_counter;
g_queue_push_tail (&onscreen->pending_frame_infos, info);
winsys = _cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_direct_scanout (onscreen, scanout);
winsys->onscreen_direct_scanout (onscreen, scanout, info);
onscreen->frame_counter++;
}

View File

@@ -178,7 +178,8 @@ cogl_onscreen_hide (CoglOnscreen *onscreen);
* Stability: unstable
*/
COGL_EXPORT void
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen);
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
CoglFrameInfo *frame_info);
/**
@@ -284,14 +285,16 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen);
COGL_EXPORT void
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
int n_rectangles,
CoglFrameInfo *info);
/**
* cogl_onscreen_direct_scanout: (skip)
*/
COGL_EXPORT void
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout);
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout,
CoglFrameInfo *info);
/**
* cogl_onscreen_swap_region:
@@ -316,7 +319,8 @@ cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
COGL_EXPORT void
cogl_onscreen_swap_region (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
int n_rectangles,
CoglFrameInfo *info);
/**
* CoglFrameEvent:

View File

@@ -402,6 +402,11 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
{
CoglContext *ctx = tex->context;
/* Since we are about to ask the GPU to generate mipmaps of tex, we
* better make sure tex is up-to-date.
*/
_cogl_texture_flush_journal_rendering (tex);
ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d);
tex_2d->mipmaps_dirty = FALSE;

View File

@@ -77,6 +77,7 @@ cogl_headers = [
'cogl-bitmap.h',
'cogl-color.h',
'cogl-context.h',
'cogl-frame-info.h',
'cogl-framebuffer.h',
'cogl-matrix.h',
'cogl-object.h',
@@ -106,7 +107,6 @@ cogl_nonintrospected_headers = [
'cogl-indices.h',
'cogl-attribute.h',
'cogl-primitive.h',
'cogl-frame-info.h',
'cogl-output.h',
'cogl-matrix-stack.h',
'cogl-poll.h',

View File

@@ -726,7 +726,8 @@ _cogl_winsys_onscreen_get_buffer_age (CoglOnscreen *onscreen)
static void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
const int *user_rectangles,
int n_rectangles)
int n_rectangles,
CoglFrameInfo *info)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
CoglRenderer *renderer = context->display->renderer;
@@ -765,7 +766,8 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
static void
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
int n_rectangles,
CoglFrameInfo *info)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
CoglRenderer *renderer = context->display->renderer;

View File

@@ -1673,7 +1673,8 @@ set_frame_info_output (CoglOnscreen *onscreen,
static void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
const int *user_rectangles,
int n_rectangles)
int n_rectangles,
CoglFrameInfo *info)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *context = framebuffer->context;
@@ -1879,7 +1880,8 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
static void
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
int n_rectangles,
CoglFrameInfo *info)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *context = framebuffer->context;

View File

@@ -116,11 +116,13 @@ typedef struct _CoglWinsysVtable
void
(*onscreen_swap_buffers_with_damage) (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
int n_rectangles,
CoglFrameInfo *info);
void
(*onscreen_direct_scanout) (CoglOnscreen *onscreen,
CoglScanout *scanout);
(*onscreen_direct_scanout) (CoglOnscreen *onscreen,
CoglScanout *scanout,
CoglFrameInfo *info);
void
(*onscreen_set_visibility) (CoglOnscreen *onscreen,
@@ -134,7 +136,8 @@ typedef struct _CoglWinsysVtable
void
(*onscreen_swap_region) (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
int n_rectangles,
CoglFrameInfo *info);
void
(*onscreen_set_resizable) (CoglOnscreen *onscreen, gboolean resizable);

View File

@@ -8,5 +8,5 @@ test_simple_rig (void)
ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
}

View File

@@ -185,9 +185,9 @@ test_multitexture (TestUtilsGTestFixture *fixture,
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
group = clutter_group_new ();
group = clutter_actor_new ();
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
/* We force continuous redrawing incase someone comments out the
@@ -197,7 +197,7 @@ test_multitexture (TestUtilsGTestFixture *fixture,
g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
clutter_actor_show_all (stage);
clutter_actor_show (stage);
clutter_main ();

View File

@@ -156,7 +156,7 @@ test_readpixels (TestUtilsGTestFixture *fixture,
ClutterActor *stage;
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
/* We force continuous redrawing of the stage, since we need to skip
* the first few frames, and we wont be doing anything else that

View File

@@ -115,9 +115,9 @@ test_texture_mipmaps (TestUtilsGTestFixture *fixture,
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
group = clutter_group_new ();
group = clutter_actor_new ();
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
/* We force continuous redrawing of the stage, since we need to skip
@@ -127,7 +127,7 @@ test_texture_mipmaps (TestUtilsGTestFixture *fixture,
g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
clutter_actor_show_all (stage);
clutter_actor_show (stage);
clutter_main ();

View File

@@ -217,14 +217,14 @@ test_texture_pixmap_x11 (TestUtilsGTestFixture *fixture,
state.pixmap = create_pixmap (&state);
state.tfp = cogl_texture_pixmap_x11_new (state.pixmap, TRUE);
clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color);
clutter_actor_set_background_color (CLUTTER_ACTOR (state.stage), &stage_color);
paint_handler = g_signal_connect_after (state.stage, "paint",
G_CALLBACK (on_paint), &state);
idle_handler = g_idle_add (queue_redraw, state.stage);
clutter_actor_show_all (state.stage);
clutter_actor_show (state.stage);
clutter_main ();

View File

@@ -394,7 +394,7 @@ test_viewport (TestUtilsGTestFixture *fixture,
ClutterActor *stage;
stage = clutter_stage_get_default ();
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
/* We force continuous redrawing of the stage, since we need to skip
* the first few frames, and we wont be doing anything else that

View File

@@ -1,5 +1,5 @@
project('mutter', 'c',
version: '3.37.2',
version: '3.37.3',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)

View File

@@ -1813,7 +1813,7 @@ msgstr ""
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Wanda ya ɓata <halin firam=\"%s\" sake girma=\"%s\" zura ido=\"%s\" salo="
"Wanda ya ɓata <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style="
"\"komene ne\"/>"
#: ../src/ui/theme.c:4704
@@ -1834,7 +1834,7 @@ msgid ""
"type=\"%s\" style_set=\"whatever\"/> element"
msgstr ""
"Babu salon firam da aka daidaita wa nau'in taga \"%s\" cikin jigon \"%s\", "
"ƙara wata ƙanshi na <nau'in taga=\"%s\" salon_daidaita=\"komene ne\"/>"
"ƙara wata ƙanshi na <window type=\"%s\" style_set=\"komene ne\"/>"
#: ../src/ui/theme.c:5295 ../src/ui/theme.c:5357 ../src/ui/theme.c:5420
#, c-format

View File

@@ -170,8 +170,6 @@ struct _MetaBackendPrivate
guint sleep_signal_id;
GCancellable *cancellable;
GDBusConnection *system_bus;
gboolean was_headless;
};
typedef struct _MetaBackendPrivate MetaBackendPrivate;
@@ -292,19 +290,6 @@ meta_backend_monitors_changed (MetaBackend *backend)
}
meta_cursor_renderer_force_update (priv->cursor_renderer);
if (meta_monitor_manager_is_headless (priv->monitor_manager) &&
!priv->was_headless)
{
clutter_stage_freeze_updates (CLUTTER_STAGE (priv->stage));
priv->was_headless = TRUE;
}
else if (!meta_monitor_manager_is_headless (priv->monitor_manager) &&
priv->was_headless)
{
clutter_stage_thaw_updates (CLUTTER_STAGE (priv->stage));
priv->was_headless = FALSE;
}
}
void

View File

@@ -32,6 +32,7 @@
#include "clutter/clutter.h"
#include "clutter/clutter-mutter.h"
#include "cogl/cogl.h"
#include "core/boxes-private.h"
#include "meta/meta-backend.h"
#include "meta/util.h"
@@ -59,7 +60,7 @@ struct _MetaCursorRendererPrivate
MetaCursorSprite *displayed_cursor;
MetaOverlay *stage_overlay;
gboolean handled_by_backend;
guint post_paint_func_id;
gulong after_paint_handler_id;
GList *hw_cursor_inhibitors;
};
@@ -153,17 +154,27 @@ queue_redraw (MetaCursorRenderer *renderer,
texture, &rect);
}
static gboolean
meta_cursor_renderer_post_paint (gpointer data)
static void
meta_cursor_renderer_after_paint (ClutterStage *stage,
ClutterStageView *stage_view,
MetaCursorRenderer *renderer)
{
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (data);
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
if (priv->displayed_cursor && !priv->handled_by_backend)
meta_cursor_renderer_emit_painted (renderer, priv->displayed_cursor);
{
graphene_rect_t rect;
MetaRectangle view_layout;
graphene_rect_t view_rect;
return TRUE;
rect = meta_cursor_renderer_calculate_rect (renderer,
priv->displayed_cursor);
clutter_stage_view_get_layout (stage_view, &view_layout);
view_rect = meta_rectangle_to_graphene_rect (&view_layout);
if (graphene_rect_intersection (&rect, &view_rect, NULL))
meta_cursor_renderer_emit_painted (renderer, priv->displayed_cursor);
}
}
static gboolean
@@ -228,11 +239,28 @@ meta_cursor_renderer_finalize (GObject *object)
if (priv->stage_overlay)
meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay);
clutter_threads_remove_repaint_func (priv->post_paint_func_id);
g_clear_signal_handler (&priv->after_paint_handler_id, stage);
G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object);
}
static void
meta_cursor_renderer_constructed (GObject *object)
{
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
ClutterActor *stage;
stage = meta_backend_get_stage (priv->backend);
priv->after_paint_handler_id =
g_signal_connect (stage, "after-paint",
G_CALLBACK (meta_cursor_renderer_after_paint),
renderer);
G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->constructed (object);
}
static void
meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
{
@@ -241,6 +269,7 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
object_class->get_property = meta_cursor_renderer_get_property;
object_class->set_property = meta_cursor_renderer_set_property;
object_class->finalize = meta_cursor_renderer_finalize;
object_class->constructed = meta_cursor_renderer_constructed;
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
obj_props[PROP_BACKEND] =
@@ -265,14 +294,6 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
static void
meta_cursor_renderer_init (MetaCursorRenderer *renderer)
{
MetaCursorRendererPrivate *priv =
meta_cursor_renderer_get_instance_private (renderer);
priv->post_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
meta_cursor_renderer_post_paint,
renderer,
NULL);
}
graphene_rect_t

View File

@@ -273,14 +273,6 @@ meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
return FALSE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return FALSE;
}
return TRUE;
}
@@ -591,6 +583,15 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
if (!stream)
@@ -628,6 +629,14 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
if (!stream)
@@ -666,6 +675,15 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
if (!stream)

View File

@@ -32,6 +32,7 @@
#include "backends/meta-renderer-view.h"
#include "backends/meta-crtc.h"
#include "backends/meta-renderer.h"
#include "clutter/clutter-mutter.h"
#include "compositor/region-utils.h"
@@ -41,6 +42,7 @@ enum
PROP_0,
PROP_TRANSFORM,
PROP_CRTC,
PROP_LAST
};
@@ -52,6 +54,8 @@ struct _MetaRendererView
ClutterStageViewCogl parent;
MetaMonitorTransform transform;
MetaCrtc *crtc;
};
G_DEFINE_TYPE (MetaRendererView, meta_renderer_view,
@@ -63,6 +67,12 @@ meta_renderer_view_get_transform (MetaRendererView *view)
return view->transform;
}
MetaCrtc *
meta_renderer_view_get_crtc (MetaRendererView *view)
{
return view->crtc;
}
static void
meta_renderer_view_get_offscreen_transformation_matrix (ClutterStageView *view,
CoglMatrix *matrix)
@@ -161,6 +171,9 @@ meta_renderer_view_get_property (GObject *object,
case PROP_TRANSFORM:
g_value_set_uint (value, view->transform);
break;
case PROP_CRTC:
g_value_set_object (value, view->crtc);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -180,6 +193,9 @@ meta_renderer_view_set_property (GObject *object,
case PROP_TRANSFORM:
meta_renderer_view_set_transform (view, g_value_get_uint (value));
break;
case PROP_CRTC:
view->crtc = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -218,5 +234,14 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_CRTC] =
g_param_spec_object ("crtc",
"MetaCrtc",
"MetaCrtc",
META_TYPE_CRTC,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
}

View File

@@ -28,4 +28,6 @@ G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view,
MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view);
MetaCrtc *meta_renderer_view_get_crtc (MetaRendererView *view);
#endif /* META_RENDERER_VIEW_H */

View File

@@ -64,6 +64,7 @@ typedef struct _MetaRendererPrivate
{
MetaBackend *backend;
GList *views;
gboolean is_paused;
} MetaRendererPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaRenderer, meta_renderer, G_TYPE_OBJECT)
@@ -127,11 +128,10 @@ create_crtc_view (MetaLogicalMonitor *logical_monitor,
gpointer user_data)
{
MetaRenderer *renderer = user_data;
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
MetaRendererView *view;
view = meta_renderer_create_view (renderer, logical_monitor, output, crtc);
priv->views = g_list_append (priv->views, view);
meta_renderer_add_view (renderer, view);
}
static void
@@ -153,12 +153,94 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
{
MetaLogicalMonitor *logical_monitor = l->data;
if (meta_logical_monitor_is_primary (logical_monitor))
{
ClutterBackend *clutter_backend;
float scale;
clutter_backend = meta_backend_get_clutter_backend (backend);
scale = meta_is_stage_views_scaled ()
? meta_logical_monitor_get_scale (logical_monitor)
: 1.f;
clutter_backend_set_fallback_resource_scale (clutter_backend, scale);
}
meta_logical_monitor_foreach_crtc (logical_monitor,
create_crtc_view,
renderer);
}
}
static MetaRendererView *
meta_renderer_get_view_for_crtc (MetaRenderer *renderer,
MetaCrtc *crtc)
{
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
GList *l;
for (l = priv->views; l; l = l->next)
{
MetaRendererView *view = l->data;
if (meta_renderer_view_get_crtc (view) == crtc)
return view;
}
return NULL;
}
typedef struct _CollectViewsData
{
MetaRenderer *renderer;
GList *out_views;
} CollectViewsData;
static gboolean
collect_views (MetaMonitor *monitor,
MetaMonitorMode *mode,
MetaMonitorCrtcMode *monitor_crtc_mode,
gpointer user_data,
GError **error)
{
CollectViewsData *data = user_data;
MetaCrtc *crtc;
MetaRendererView *view;
crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output);
view = meta_renderer_get_view_for_crtc (data->renderer, crtc);
if (!g_list_find (data->out_views, view))
data->out_views = g_list_prepend (data->out_views, view);
return TRUE;
}
static GList *
meta_renderer_real_get_views_for_monitor (MetaRenderer *renderer,
MetaMonitor *monitor)
{
CollectViewsData data = { 0 };
MetaMonitorMode *monitor_mode;
data.renderer = renderer;
monitor_mode = meta_monitor_get_current_mode (monitor);
meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
collect_views,
&data,
NULL);
return data.out_views;
}
GList *
meta_renderer_get_views_for_monitor (MetaRenderer *renderer,
MetaMonitor *monitor)
{
return META_RENDERER_GET_CLASS (renderer)->get_views_for_monitor (renderer,
monitor);
}
void
meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererView *view)
@@ -166,6 +248,14 @@ meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
priv->views = g_list_append (priv->views, view);
if (priv->is_paused)
{
ClutterFrameClock *frame_clock =
clutter_stage_view_get_frame_clock (CLUTTER_STAGE_VIEW (view));
clutter_frame_clock_inhibit (frame_clock);
}
}
/**
@@ -186,6 +276,44 @@ meta_renderer_get_views (MetaRenderer *renderer)
return priv->views;
}
void
meta_renderer_pause (MetaRenderer *renderer)
{
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
GList *l;
g_return_if_fail (!priv->is_paused);
priv->is_paused = TRUE;
for (l = priv->views; l; l = l->next)
{
ClutterStageView *stage_view = l->data;
ClutterFrameClock *frame_clock =
clutter_stage_view_get_frame_clock (stage_view);
clutter_frame_clock_inhibit (frame_clock);
}
}
void
meta_renderer_resume (MetaRenderer *renderer)
{
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
GList *l;
g_return_if_fail (priv->is_paused);
priv->is_paused = FALSE;
for (l = priv->views; l; l = l->next)
{
ClutterStageView *stage_view = l->data;
ClutterFrameClock *frame_clock =
clutter_stage_view_get_frame_clock (stage_view);
clutter_frame_clock_uninhibit (frame_clock);
}
}
gboolean
meta_renderer_is_hardware_accelerated (MetaRenderer *renderer)
{
@@ -265,6 +393,7 @@ meta_renderer_class_init (MetaRendererClass *klass)
object_class->finalize = meta_renderer_finalize;
klass->rebuild_views = meta_renderer_real_rebuild_views;
klass->get_views_for_monitor = meta_renderer_real_get_views_for_monitor;
obj_props[PROP_BACKEND] =
g_param_spec_object ("backend",

View File

@@ -46,6 +46,8 @@ struct _MetaRendererClass
MetaOutput *output,
MetaCrtc *crtc);
void (* rebuild_views) (MetaRenderer *renderer);
GList * (* get_views_for_monitor) (MetaRenderer *renderer,
MetaMonitor *monitor);
};
MetaBackend * meta_renderer_get_backend (MetaRenderer *renderer);
@@ -57,9 +59,16 @@ void meta_renderer_rebuild_views (MetaRenderer *renderer);
void meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererView *view);
GList * meta_renderer_get_views_for_monitor (MetaRenderer *renderer,
MetaMonitor *monitor);
META_EXPORT_TEST
GList * meta_renderer_get_views (MetaRenderer *renderer);
gboolean meta_renderer_is_hardware_accelerated (MetaRenderer *renderer);
void meta_renderer_pause (MetaRenderer *renderer);
void meta_renderer_resume (MetaRenderer *renderer);
#endif /* META_RENDERER_H */

View File

@@ -149,16 +149,32 @@ is_cursor_in_stream (MetaScreenCastAreaStreamSrc *area_src)
}
}
static gboolean
is_redraw_queued (MetaScreenCastAreaStreamSrc *area_src)
{
ClutterStage *stage = get_stage (area_src);
GList *l;
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *view = l->data;
if (clutter_stage_is_redraw_queued_on_view (stage, view))
return TRUE;
}
return FALSE;
}
static void
sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
ClutterStage *stage = get_stage (area_src);
if (!is_cursor_in_stream (area_src))
return;
if (clutter_stage_is_redraw_queued (stage))
if (is_redraw_queued (area_src))
return;
meta_screen_cast_stream_src_maybe_record_frame (src);

View File

@@ -176,16 +176,37 @@ is_cursor_in_stream (MetaScreenCastMonitorStreamSrc *monitor_src)
}
}
static gboolean
is_redraw_queued (MetaScreenCastMonitorStreamSrc *monitor_src)
{
MetaBackend *backend = get_backend (monitor_src);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
ClutterStage *stage = get_stage (monitor_src);
MetaMonitor *monitor = get_monitor (monitor_src);
g_autoptr (GList) views = NULL;
GList *l;
views = meta_renderer_get_views_for_monitor (renderer, monitor);
for (l = views; l; l = l->next)
{
MetaRendererView *view = l->data;
if (clutter_stage_is_redraw_queued_on_view (stage, CLUTTER_STAGE_VIEW (view)))
return TRUE;
}
return FALSE;
}
static void
sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
ClutterStage *stage = get_stage (monitor_src);
if (!is_cursor_in_stream (monitor_src))
return;
if (clutter_stage_is_redraw_queued (stage))
if (is_redraw_queued (monitor_src))
return;
meta_screen_cast_stream_src_maybe_record_frame (src);
@@ -371,12 +392,12 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor;
stage = get_stage (monitor_src);
if (!clutter_stage_is_redraw_queued (stage))
if (!is_redraw_queued (monitor_src))
return FALSE;
monitor = get_monitor (monitor_src);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
stage = get_stage (monitor_src);
clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
return TRUE;

View File

@@ -781,7 +781,6 @@ void
meta_backend_native_pause (MetaBackendNative *native)
{
MetaBackend *backend = META_BACKEND (native);
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaMonitorManagerKms *monitor_manager_kms =
@@ -789,12 +788,13 @@ meta_backend_native_pause (MetaBackendNative *native)
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
MetaSeatNative *seat =
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
MetaRenderer *renderer = meta_backend_get_renderer (backend);
COGL_TRACE_BEGIN_SCOPED (MetaBackendNativePause,
"Backend (pause)");
meta_seat_native_release_devices (seat);
clutter_stage_freeze_updates (stage);
meta_renderer_pause (renderer);
disconnect_udev_device_added_handler (native);
@@ -814,6 +814,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
MetaSeatNative *seat =
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
MetaRenderer *renderer = meta_backend_get_renderer (backend);
COGL_TRACE_BEGIN_SCOPED (MetaBackendNativeResume,
"Backend (resume)");
@@ -823,7 +824,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
connect_udev_device_added_handler (native);
meta_seat_native_reclaim_devices (seat);
clutter_stage_thaw_updates (stage);
meta_renderer_resume (renderer);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));

View File

@@ -169,8 +169,6 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
MetaDumbBuffer dumb_fbs[2];
} cpu;
int pending_flips;
gboolean noted_primary_gpu_copy_ok;
gboolean noted_primary_gpu_copy_failed;
MetaSharedFramebufferImportStatus import_status;
@@ -199,15 +197,9 @@ typedef struct _MetaOnscreenNative
} egl;
#endif
gboolean pending_swap_notify;
gboolean pending_set_crtc;
int64_t pending_queue_swap_notify_frame_count;
int64_t pending_swap_notify_frame_count;
MetaRendererView *view;
int total_pending_flips;
} MetaOnscreenNative;
struct _MetaRendererNative
@@ -224,7 +216,6 @@ struct _MetaRendererNative
CoglClosure *swap_notify_idle;
int64_t frame_counter;
gboolean pending_unset_disabled_crtcs;
GList *power_save_page_flip_onscreens;
@@ -721,60 +712,6 @@ meta_renderer_native_disconnect (CoglRenderer *cogl_renderer)
g_slice_free (CoglRendererEGL, cogl_renderer_egl);
}
static void
flush_pending_swap_notify (CoglFramebuffer *framebuffer)
{
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
if (onscreen_native->pending_swap_notify)
{
CoglFrameInfo *info;
while ((info = g_queue_peek_head (&onscreen->pending_frame_infos)) &&
info->global_frame_counter <= onscreen_native->pending_swap_notify_frame_count)
{
_cogl_onscreen_notify_frame_sync (onscreen, info);
_cogl_onscreen_notify_complete (onscreen, info);
cogl_object_unref (info);
g_queue_pop_head (&onscreen->pending_frame_infos);
}
onscreen_native->pending_swap_notify = FALSE;
cogl_object_unref (onscreen);
}
}
}
static void
flush_pending_swap_notify_idle (void *user_data)
{
CoglContext *cogl_context = user_data;
CoglRendererEGL *cogl_renderer_egl = cogl_context->display->renderer->winsys;
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
GList *l;
/* This needs to be disconnected before invoking the callbacks in
* case the callbacks cause it to be queued again */
_cogl_closure_disconnect (renderer_native->swap_notify_idle);
renderer_native->swap_notify_idle = NULL;
l = cogl_context->framebuffers;
while (l)
{
GList *next = l->next;
CoglFramebuffer *framebuffer = l->data;
flush_pending_swap_notify (framebuffer);
l = next;
}
}
static void
free_current_secondary_bo (CoglOnscreen *onscreen)
{
@@ -802,40 +739,14 @@ free_current_bo (CoglOnscreen *onscreen)
static void
meta_onscreen_native_queue_swap_notify (CoglOnscreen *onscreen)
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
CoglFrameInfo *info;
onscreen_native->pending_swap_notify_frame_count =
onscreen_native->pending_queue_swap_notify_frame_count;
g_assert (onscreen->pending_frame_infos.length == 1);
if (onscreen_native->pending_swap_notify)
return;
/* We only want to notify that the swap is complete when the
* application calls cogl_context_dispatch so instead of
* immediately notifying we queue an idle callback */
if (!renderer_native->swap_notify_idle)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *cogl_context = framebuffer->context;
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
renderer_native->swap_notify_idle =
_cogl_poll_renderer_add_idle (cogl_renderer,
flush_pending_swap_notify_idle,
cogl_context,
NULL);
}
/*
* The framebuffer will have its own referenc while the swap notify is
* pending. Otherwise when destroying the view would drop the pending
* notification with if the destruction happens before the idle callback
* is invoked.
*/
cogl_object_ref (onscreen);
onscreen_native->pending_swap_notify = TRUE;
info = g_queue_pop_head (&onscreen->pending_frame_infos);
_cogl_onscreen_notify_frame_sync (onscreen, info);
_cogl_onscreen_notify_complete (onscreen, info);
cogl_object_unref (info);
}
static gboolean
@@ -1148,10 +1059,9 @@ notify_view_crtc_presented (MetaRendererView *view,
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
CoglFrameInfo *frame_info;
MetaCrtc *crtc;
MetaGpuKms *gpu_kms;
MetaRendererNativeGpuData *renderer_gpu_data;
/* Only keep the frame info for the fastest CRTC in use, which may not be
* the first one to complete a flip. By only telling the compositor about the
@@ -1163,35 +1073,21 @@ notify_view_crtc_presented (MetaRendererView *view,
crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc));
maybe_update_frame_info (crtc, frame_info, time_ns);
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
if (gpu_kms != render_gpu)
meta_onscreen_native_queue_swap_notify (onscreen);
renderer_gpu_data =
meta_renderer_native_get_gpu_data (renderer_native,
onscreen_native->render_gpu);
switch (renderer_gpu_data->mode)
{
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state =
onscreen_native->secondary_gpu_state;
secondary_gpu_state->pending_flips--;
}
onscreen_native->total_pending_flips--;
if (onscreen_native->total_pending_flips == 0)
{
MetaRendererNativeGpuData *renderer_gpu_data;
meta_onscreen_native_queue_swap_notify (onscreen);
renderer_gpu_data =
meta_renderer_native_get_gpu_data (renderer_native,
onscreen_native->render_gpu);
switch (renderer_gpu_data->mode)
{
case META_RENDERER_NATIVE_MODE_GBM:
meta_onscreen_native_swap_drm_fb (onscreen);
break;
case META_RENDERER_NATIVE_MODE_GBM:
meta_onscreen_native_swap_drm_fb (onscreen);
break;
#ifdef HAVE_EGL_DEVICE
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
break;
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
break;
#endif
}
}
}
@@ -1405,10 +1301,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
g_object_ref (view),
kms_update);
onscreen_native->total_pending_flips++;
if (secondary_gpu_state)
secondary_gpu_state->pending_flips++;
break;
#ifdef HAVE_EGL_DEVICE
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
@@ -1418,7 +1310,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
g_object_ref (view),
custom_egl_stream_page_flip,
onscreen_native);
onscreen_native->total_pending_flips++;
break;
#endif
}
@@ -1486,40 +1377,6 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen,
}
}
static void
wait_for_pending_flips (CoglOnscreen *onscreen)
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
GError *error = NULL;
secondary_gpu_state = onscreen_native->secondary_gpu_state;
if (secondary_gpu_state)
{
while (secondary_gpu_state->pending_flips)
{
if (!meta_gpu_kms_wait_for_flip (secondary_gpu_state->gpu_kms, &error))
{
g_warning ("Failed to wait for flip on secondary GPU: %s",
error->message);
g_clear_error (&error);
break;
}
}
}
while (onscreen_native->total_pending_flips)
{
if (!meta_gpu_kms_wait_for_flip (onscreen_native->render_gpu, &error))
{
g_warning ("Failed to wait for flip: %s", error->message);
g_clear_error (&error);
break;
}
}
}
static gboolean
import_shared_framebuffer (CoglOnscreen *onscreen,
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
@@ -2067,9 +1924,10 @@ ensure_crtc_modes (CoglOnscreen *onscreen,
}
static void
meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles)
meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles,
CoglFrameInfo *frame_info)
{
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
@@ -2084,7 +1942,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
CoglFrameInfo *frame_info;
gboolean egl_context_changed = FALSE;
MetaKmsUpdate *kms_update;
g_autoptr (GError) error = NULL;
@@ -2096,23 +1953,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
kms_update = meta_kms_ensure_pending_update (kms);
/*
* Wait for the flip callback before continuing, as we might have started the
* animation earlier due to the animation being driven by some other monitor.
*/
COGL_TRACE_BEGIN (MetaRendererNativeSwapBuffersWait,
"Onscreen (waiting for page flips)");
wait_for_pending_flips (onscreen);
COGL_TRACE_END (MetaRendererNativeSwapBuffersWait);
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
frame_info->global_frame_counter = renderer_native->frame_counter;
update_secondary_gpu_state_pre_swap_buffers (onscreen);
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
rectangles,
n_rectangles);
n_rectangles,
frame_info);
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
@@ -2146,8 +1992,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
ensure_crtc_modes (onscreen, kms_update);
onscreen_native->pending_queue_swap_notify_frame_count = renderer_native->frame_counter;
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
/*
@@ -2296,8 +2140,9 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
}
static void
meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout)
meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout,
CoglFrameInfo *frame_info)
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
@@ -2311,17 +2156,11 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
MetaBackend *backend = meta_renderer_get_backend (renderer);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
CoglFrameInfo *frame_info;
MetaKmsUpdate *kms_update;
g_autoptr (GError) error = NULL;
kms_update = meta_kms_ensure_pending_update (kms);
wait_for_pending_flips (onscreen);
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
frame_info->global_frame_counter = renderer_native->frame_counter;
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
@@ -2331,9 +2170,6 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout));
ensure_crtc_modes (onscreen, kms_update);
onscreen_native->pending_queue_swap_notify_frame_count =
renderer_native->frame_counter;
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
meta_kms_post_pending_update_sync (kms);
@@ -3247,12 +3083,15 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
&view_layout);
view = g_object_new (META_TYPE_RENDERER_VIEW,
"name", meta_output_get_name (output),
"stage", meta_backend_get_stage (backend),
"layout", &view_layout,
"crtc", crtc,
"scale", scale,
"framebuffer", onscreen,
"offscreen", offscreen,
"use-shadowfb", use_shadowfb,
"transform", view_transform,
"refresh-rate", crtc_mode_info->refresh_rate,
NULL);
g_clear_pointer (&offscreen, cogl_object_unref);
@@ -3305,8 +3144,6 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
MetaKms *kms = meta_backend_native_get_kms (backend_native);
MetaKmsUpdate *kms_update = NULL;
renderer_native->frame_counter++;
if (renderer_native->pending_unset_disabled_crtcs)
{
GList *l;
@@ -3346,12 +3183,6 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
}
}
int64_t
meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native)
{
return renderer_native->frame_counter;
}
static gboolean
create_secondary_egl_config (MetaEgl *egl,
MetaRendererNativeMode mode,

View File

@@ -55,8 +55,6 @@ MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_
void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
uint32_t drm_format,
uint64_t drm_modifier,

View File

@@ -885,13 +885,9 @@ meta_event_prepare (GSource *source,
{
gboolean retval;
_clutter_threads_acquire_lock ();
*timeout = -1;
retval = clutter_events_pending ();
_clutter_threads_release_lock ();
return retval;
}
@@ -901,13 +897,9 @@ meta_event_check (GSource *source)
MetaEventSource *event_source = (MetaEventSource *) source;
gboolean retval;
_clutter_threads_acquire_lock ();
retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
clutter_events_pending ());
_clutter_threads_release_lock ();
return retval;
}
@@ -1273,8 +1265,6 @@ meta_event_dispatch (GSource *g_source,
MetaSeatNative *seat;
ClutterEvent *event;
_clutter_threads_acquire_lock ();
seat = source->seat;
/* Don't queue more events if we haven't finished handling the previous batch
@@ -1299,7 +1289,7 @@ meta_event_dispatch (GSource *g_source,
/* Drop events if we don't have any stage to forward them to */
if (!_clutter_input_device_get_stage (input_device))
goto out;
return TRUE;
/* update the device states *before* the event */
event_state = seat->button_state |
@@ -1311,9 +1301,6 @@ meta_event_dispatch (GSource *g_source,
_clutter_stage_queue_event (event->any.stage, event, FALSE);
}
out:
_clutter_threads_release_lock ();
return TRUE;
}
static GSourceFuncs event_funcs = {

View File

@@ -147,24 +147,6 @@ struct _MetaSeatNative
G_DECLARE_FINAL_TYPE (MetaSeatNative, meta_seat_native,
META, SEAT_NATIVE, ClutterSeat)
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);
}
void meta_seat_native_notify_key (MetaSeatNative *seat,
ClutterInputDevice *device,
uint64_t time_us,

View File

@@ -52,86 +52,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaStageNative, meta_stage_native,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init))
static void
frame_cb (CoglOnscreen *onscreen,
CoglFrameEvent frame_event,
CoglFrameInfo *frame_info,
void *user_data)
{
MetaStageNative *stage_native = user_data;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_native);
int64_t global_frame_counter;
int64_t presented_frame_counter;
ClutterFrameInfo clutter_frame_info;
global_frame_counter = cogl_frame_info_get_global_frame_counter (frame_info);
switch (frame_event)
{
case COGL_FRAME_EVENT_SYNC:
presented_frame_counter = stage_native->presented_frame_counter_sync;
stage_native->presented_frame_counter_sync = global_frame_counter;
break;
case COGL_FRAME_EVENT_COMPLETE:
presented_frame_counter = stage_native->presented_frame_counter_complete;
stage_native->presented_frame_counter_complete = global_frame_counter;
break;
default:
g_assert_not_reached ();
}
if (global_frame_counter <= presented_frame_counter)
return;
clutter_frame_info = (ClutterFrameInfo) {
.frame_counter = global_frame_counter,
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info),
.presentation_time = cogl_frame_info_get_presentation_time (frame_info)
};
_clutter_stage_cogl_presented (stage_cogl, frame_event, &clutter_frame_info);
}
static void
ensure_frame_callback (MetaStageNative *stage_native,
ClutterStageView *stage_view)
{
CoglFramebuffer *framebuffer;
CoglOnscreen *onscreen;
CoglClosure *closure;
closure = g_object_get_qdata (G_OBJECT (stage_view),
quark_view_frame_closure);
if (closure)
return;
framebuffer = clutter_stage_view_get_onscreen (stage_view);
onscreen = COGL_ONSCREEN (framebuffer);
closure = cogl_onscreen_add_frame_callback (onscreen,
frame_cb,
stage_native,
NULL);
g_object_set_qdata (G_OBJECT (stage_view),
quark_view_frame_closure,
closure);
}
static void
ensure_frame_callbacks (MetaStageNative *stage_native)
{
MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend);
GList *l;
for (l = meta_renderer_get_views (renderer); l; l = l->next)
{
ClutterStageView *stage_view = l->data;
ensure_frame_callback (stage_native, stage_view);
}
}
void
meta_stage_native_rebuild_views (MetaStageNative *stage_native)
{
@@ -141,7 +61,6 @@ meta_stage_native_rebuild_views (MetaStageNative *stage_native)
meta_renderer_rebuild_views (renderer);
clutter_stage_clear_stage_views (CLUTTER_STAGE (stage));
ensure_frame_callbacks (stage_native);
}
static gboolean
@@ -186,16 +105,6 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window)
return meta_renderer_get_views (renderer);
}
static int64_t
meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window)
{
MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
return meta_renderer_native_get_frame_counter (renderer_native);
}
static void
meta_stage_native_finish_frame (ClutterStageWindow *stage_window)
{
@@ -225,6 +134,5 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
iface->can_clip_redraws = meta_stage_native_can_clip_redraws;
iface->get_geometry = meta_stage_native_get_geometry;
iface->get_views = meta_stage_native_get_views;
iface->get_frame_counter = meta_stage_native_get_frame_counter;
iface->finish_frame = meta_stage_native_finish_frame;
}

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