Compare commits

...

238 Commits

Author SHA1 Message Date
efb1ee9730 Bump version to 3.32.0
Update NEWS.
2019-03-11 18:45:20 +01:00
a871d56f88 cogl: Revert swizzling for BGRA buffers
As it was originally reported on
https://bugzilla.gnome.org/show_bug.cgi?id=779234#c0, the hottest path was
convert_ubyte() in mesa. Reverting this shows no trace of those hot paths,
nor any higher than usual CPU activity.

As the improvements at the time were real, I can only conclude that pixel
conversion was happening somewhere further the pipeline, and swizzling just
helped indirectly. That got eventually fixed, so swizzling just stayed to
cause grief. And lots it caused.

Time to bin this, it seems.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/486
2019-03-08 10:41:25 +01:00
d83a325f98 Revert "Revert "cogl: Pick glReadPixels format by target, not source""
This reverts commit 4f72099023.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/486
2019-03-07 23:04:55 +01:00
4f72099023 Revert "cogl: Pick glReadPixels format by target, not source"
This reverts commit 981b045459.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/418
2019-03-06 17:02:00 +01:00
8856a396fd sound-player: Don't deadlock in finish_cb
The function finish_cb can be called as a result of a call to ca_context_cancel
in cancelled_cb. This will result in a deadlock because, as per documentation,
g_cancellable_disconnect cannot be called inside the cancellable handler.

It is possible to detect if the call to finish_cb is caused by ca_context_cancel
checking if error_code == CA_ERROR_CANCELED. To avoid the deadlock we should
call g_signal_handler_disconnect instead g_cancellable_disconnect if this is the
case.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/474
2019-03-05 12:07:41 +00:00
b0fb39bb54 Bump version to 3.31.92
Update NEWS.
2019-03-05 04:39:08 +01:00
7abceb434d x11-display: Split out restoring of active workspace
Splitting out the X11 display initialization from display_open() broke
restoring the previously active workspace in two ways:

 - when dynamic workspaces are used, the old workspaces haven't
   been restored yet, so we stay on the first workspace

 - when static workspaces are used, the code tries to access
   the compositor that hasn't been initialized yet, resulting
   in a segfault

Fix both those issues by splitting out restoring of the active workspace.

https://gitlab.gnome.org/GNOME/mutter/issues/479
2019-03-04 19:42:00 +00:00
3e472faf5c wayland: Minor refactor
We use the input_method on both branches, but only check for its existence
when enabling the text_input. The case of focusing out shouldn't happen in
practice as we couldn't have focused in ever before, but still make the
check one level above so it's clearer that the text_input's IM focus cannot
be enabled without an IM implementation.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/432
2019-03-04 18:17:08 +00:00
eabb789381 wayland: Only enable OSK if receiving .enable when already active
Enable the OSK if receiving .enable consecutively (i.e. the
ClutterInputFocus was already focused). We specifically want to avoid
enabling the panel just because of focus changes within a surface (where
the .disable request across focus change would previously unfocus the
ClutterInputFocus). Prior state should be preserved if possible in that
situation.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/432
2019-03-04 18:17:08 +00:00
1f1f49dc79 clutter: Do not toggle the OSK panel off after focus out
Let the upper layers figure out whether the panel should be shown
or hidden.

https://gitlab.gnome.org/GNOME/gtk/issues/1277
https://gitlab.gnome.org/GNOME/mutter/merge_requests/432
2019-03-04 18:17:08 +00:00
3fd0e23ed9 clutter: Make ClutterInputFocus API to set panel state explicit
Before we just had API to toggle the OSK panel state. Make this API
generic so the upper layers may set the state as they see fit.
All callers have been updated.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/432
2019-03-04 18:17:08 +00:00
033a771e8c clutter: Remove clutter_set_windowing_backend()
This is a choice imposed by mutter, not something you can usefully set
from the config file.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/463
2019-03-04 09:28:30 -05:00
6cbaeae64d clutter: remove x11/clutter-x11-texure-pixmap.c
We're not using this, our path to BindTexImage is hidden down in cogl
instead. In general we should reduce the amount of X-specific API we
expose.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/463
2019-03-04 09:28:30 -05:00
6a5772c881 clutter: Remove tests/interactive/text-pixmap.c
This is the only consumer of clutter_x11_texture_pixmap_*

https://gitlab.gnome.org/GNOME/mutter/merge_requests/463
2019-03-04 09:27:25 -05:00
ed17559f88 clutter/evdev: Use internal button codes for mousekeys
The ClutterVirtualInputDevice API was fixed to use Clutter button
internal codes, whereas the mousekeys still uses evdev codes.

Change the mousekeys implementation to use the Clutter button code
instead to remain compatible with the ClutterVirtualInputDevice API.

Fixes: 24aef44b (Translate from button internal codes to evdev)
https://gitlab.gnome.org/GNOME/mutter/merge_requests/473
2019-03-04 13:47:26 +01:00
58cc4c2433 Update Dutch translation 2019-03-03 20:20:59 +00:00
4a65897567 Update Latvian translation 2019-03-03 10:50:28 +00:00
e0811ce141 clutter/x11: Consider remapped keys when guessing the keycode from the keysym
Since e3e933c4 a keyval can be temporarily remapped to an unused keycode. Due to
some limitations in XTestFakeKeyEvent, the remapping has to be done in the first
xkb group/layout. In case there are two or more keyboard layouts enabled and the
selected keyboard layout is not the first, clutter_keymap_x11_keycode_for_keyval
will fail to retrieve the correct keycode for a remapped keyval. Let's use the
reserved_keycodes map in order to retrieve the correct keycode if needed.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/443
2019-03-02 13:20:30 +00:00
d597449a0e Update POTFILES.skip
https://gitlab.gnome.org/GNOME/mutter/merge_requests/471
2019-03-02 12:35:34 +01:00
cbd3ad8585 clutter/stage-cogl: Add function to scale and clamp fractional values to pixels
Compute pixels rectangles using various clutter utility functions that take
care of the subpixel compensation.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:48:40 +01:00
3d89b47757 clutter/stage-cogl: Cleanup the code for scissor region calculation
Ignore the subpixel compensation when this value isn't set, and directly
set the passed rect.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:42:08 +01:00
8b09542fd9 boxes: Crop rectangle converting to integer with grow strategy
Reuse meta_rectangle_from_clutter_rect with growing strategy to properly cast
the clutter floating rectangle to integer MetaRectangle.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:42:08 +01:00
e5a9e9c93b clutter/util: Add functions for managing cairo and clutter rects
Utility functions to easily convert from ClutterRect to cairo int rects and
vice-versa.

And add ability to offset a cairo rect.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:42:08 +01:00
a8c972cd6b boxes: Add function to create a rectangle from floating clutter rect
Meta rectangles are integer based while clutter works in floating coordinates,
so when converting to integers we need a strategy.

Implement the shrink strategy by ceiling the coordinates and flooring the width,
and the grow strategy reusing clutter facility for this.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:42:07 +01:00
9d9d455bba clutter/rect: Add utility function to scale the rectangle
Scale coordinates and size of the rectangle by the passed value.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:42:07 +01:00
8bc8dc66f2 clutter/rect: Clamp to pixel taking care of subpixel values
The clamped rectangle currently could not fully contain the original fractional
rectangle because it doesn't take care of the fact that the new width should
consider the fact that flooring we'd translate the rectangle, and thus to cover
the same area we need to take care of it.

So, to properly compute the width and height, calculate x2 and y2 first and then
use this ceiled value to compute the actual width using the floored x1 and y1.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 19:22:03 +01:00
ceb4fe2151 wayland-tablet-tool: Downscale the sprite texture in FB mode
When using scaled framebuffer we need to downscale the texture size in order
to get the cursor properly drawn at its real size and in good quality.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
412d5685ba clutter/stage: Add view scale support on read_pixels()
https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
baf98bb205 clutter/stage: Avoid duplicating code for capturing
https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
f2c033b1b4 clutter/stage: Add scaling support to capture_view_into
https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
4be4d85f84 clutter/stage: Cleanup the capture_view code
Reuse capture's rect parameter instead of passing a new one, and support the
case where there are no returned areas.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
c695471475 clutter/stage: Add private API to get max view scale for rect
Move the same code from ClutterActor as this is something we can
reuse elsewhere.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
97a3b88f25 clutter/stage: Use rounded values to create image surfaces
This needs to be an integer, and since the assumptions we
have in Monitor this multiplication should always return
an integer, however in case of precision loss it could
return something very close to the next/prev integer, so
let's be sure this won't happen, by just rounding it.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
1e1cb4961b clutter/offscreen-effect: Make sure we use linear filter for fractional scaling
When we try to update the FB, we might face the case in which the effect target
framebuffer does not need any redraw, because it's already properly sized and
scaled, but the filter applied to the pipeline is not, because it has been
computed for a non-fractional scaling.

This is happens for example to clutter actors with a flattening effect (i.e.
override redirect mode set), that might have been generated properly for a
celied scaling level, but when we go fractional we need to ensure to use a
linear filter, as the 1:1 texel:pixel assumption is not true anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
e3966882e8 clutter/offscreen-effect: Support adding effect to resource scaled actors
At this level we use ceiled resource-scale when painting fractional value

When using fractional scaling we still need to create an integer-sized
texture and then we should paint it using a size which is proportional
to the real actor size ratio, and only paint a subsample of it, but this
doesn't seem to work properly with some weird scaling values.

Then, it's just better to draw the texture ceiled and then we scale it
down to match the proper actor scaling at paint level.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
af3662775e clutter/text: Generate resource scaled text and paint it at proper scaling
When resource scale is set we need to generate a scaled PangoLayout (by adding
a new scale attribute, or adjusting the one we already have according the
resource scale), then it has to be painted with proper scaling matrix.

So everything that has to do with PangoLayout has to be in real coordinates,
then clutter logical coords multiplied by resource scaling.
While the actual size of the layout is the one of the PangoLayout divided by
resource scale.

We map the text positions to logical coords by default, while using
the pixel coordinates when painting.

We fall back to scale 1 when calculating preferred size if no scale is
known. The pango layout will not have set a layout scale attribute,
meaning it'll be 1, thus we should just assume the layout scale is 1 here.
Not doing so might result in the preferred size being 0x0 meaning the
actor won't be laid out properly.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/135

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
9234777e36 clutter/text: Add utility function to set the pango attributes
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
02813d74e1 clutter/canvas: Implement clutter_canvas_{get,set}_scale_factor
https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
d3beb3ddb7 clutter/actor-box: Add clutter_actor_box_scale function
This allows to scale the box by given factor

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
ad5555bf42 clutter: Add API to get the resource scale of an actor
A clutter actor might be painted on a stage view with a view scale
other than 1. In this case, to show the content in full resolution, the
actor must use a higher resolution resource (e.g. texture), which will
be down scaled to the stage coordinate space, then scaled up again to
the stage view framebuffer scale.

Use a 'resource-scale' property to save information and notify when it
changes.

The resource scale is the ceiled value of the highest stage view scale a
actor is visible on. The value is ceiled because using a higher
resolution resource consistently results in better output quality. One
reason for this is that rendering is often not perfectly pixel aligned,
meaning even if we load a resource with a suitable size, due to us still
scaling ever so slightly, the quality is affected. Using a higher
resolution resource avoids this problem.

For situations inside clutter where the actual maximum view scale is
needed, a function _clutter_actor_get_real_resource_scale() is provided,
which returns the non-ceiled value.

Make sure we ignore resource scale computation requests during size
requests or allocation while ensure we've proper resource-scale on
pre-paint.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
789a3ef029 clutter/util: Add function to build a ClutterRect from a cairo rectangle
Utility functions to easily convert a cairo rectangle into a ClutterRect.

And add ability to offset a cairo rect.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
3512647419 background: Use monitor scale to generate the texture at real monitor size
We need to use pixel size of the monitor in order to generate a valid
texture with full quality for current monitor

In spanned case the background should cover all the differently scaled monitors
thus we scale the texture up to the maximum scaling level and then we resample
it drawing only each side in the monitor it should occupy using the proper
scaling level.

In wallpaper mode (or color mode) for example we don't need to scale the area,
also the texture size we return should be unscaled, not to confuse
MetaBackgroundActor making it use more space than needed.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:46:49 +00:00
42953a50bb stage: Queue redraw previous Rect only if it has changed
No need to queue redraw the same area multiple times, so we can avoid the
computation involved with it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
f4c2b69934 stage: Clamp to pixel the redraw clip taking care of the floored coords
When we floor the quad coordinates then we've also to enlarge the quad by the
difference between the floored value and the actual coordinate, otherwise
we'd end up in a smaller quad.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
d7ec5d3022 stage: Add utility function to queue draw a ClutterRect
Remove duplicated code to clamp to pixel

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
2019-03-01 17:46:49 +00:00
7442de81bb display: Add meta_display_get_monitor_scale
This will return the monitor scaling for the requested logical screen

https://bugzilla.gnome.org/show_bug.cgi?id=765011
2019-03-01 17:46:49 +00:00
f76b3edf9c monitor: Define scale_steps globally
No need to compute the scale steps multiple times, since
it's just a defined value, so let's use a define for this
avoiding to pass around.

https://bugzilla.gnome.org/show_bug.cgi?id=782742
2019-03-01 17:46:49 +00:00
c67b0bd7e2 Updated Spanish translation 2019-03-01 12:20:26 +01:00
5356cd3c7d Update Serbian translation 2019-02-28 20:25:58 +00:00
bc657c9feb clutter: Remove unused deprecated/clutter-input-device-deprecated.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/464
2019-02-28 13:01:36 -05:00
52e074b08a clutter: Remove unused deprecated/clutter-{list-,}model.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/464
2019-02-28 13:01:32 -05:00
f1b148e488 clutter: Remove tests/conform/model.c
The clutter model code is deprecated and this is the only consumer.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/464
2019-02-28 13:01:29 -05:00
df3d2389a9 clutter: Remove unused deprecated/clutter-behaviour-rotate.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/461
2019-02-28 10:51:12 -05:00
ac7ca3265e clutter: Remove tests/interactive/test-{depth,multistage.c}
These are the only consumers of deprecated/clutter-behaviour-rotate.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/461
2019-02-28 10:35:39 -05:00
cc07702386 clutter: Remove unused deprecated/clutter-behaviour-path.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/461
2019-02-28 10:35:29 -05:00
1f796f1fbf clutter: Remove unused deprecated/clutter-timeout-interval.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/461
2019-02-28 10:35:29 -05:00
65312be59d clutter: Remove unused deprecated/clutter-behaviour-ellipse.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/461
2019-02-28 10:35:29 -05:00
5a6a602da8 clutter: Remove unused deprecated/clutter-shader.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/461
2019-02-28 10:35:29 -05:00
8d9a5e3c7e wayland/touch: Remove undelivered touches earlier
When the touch_down event was not delivered to Wayland clients, there's
no point in keeping the touchpoint in our list, so remove it early
inside update() instead of removing it after the touch ended.

This fixes a crash inside touch_handle_surface_destroy() where the
assertion to make sure the surface is removed fails because the
touch_count of the surface never reached 0. This in turn happened
because a new sequence was added, while a (already ended one) wasn't
removed from the touch->touches list before. This caused the touch
counter to get incremented by 1 while no new sequence was added to the
list (because Clutter reuses sequence IDs, the old sequence is equal to
the new one, i.e. the new sequence already is present in the list).

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/200

https://gitlab.gnome.org/GNOME/mutter/merge_requests/426
2019-02-28 09:52:23 +00:00
1c6ea5d1db Use a consistent style for enum braces
https://gitlab.gnome.org/GNOME/mutter/merge_requests/361
2019-02-28 09:31:01 +01:00
ca0b6fc3ac Update Korean translation 2019-02-28 03:16:37 +00:00
7c3a0d54cc Updated Vietnamese translation
Signed-off-by: Trần Ngọc Quân <vnwildman@gmail.com>
2019-02-28 07:47:58 +07:00
16a2eab290 clutter: Animatable: Use G_DECLARE_INTERFACE()
It cuts away a bit of the GObject boilerplate, gives us support for
`g_autoptr`, and removes the typedef hack inside clutter-scroll-actor.c.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/380
2019-02-27 16:44:24 +00:00
41a69f194d clutter: MasterClock: Use G_DECLARE_INTERFACE()
It cuts away a bit of the GObject boilerplate, gives us support for
`g_autoptr`, and removes the typedef hack inside clutter-master-clock.c.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/380
2019-02-27 16:44:24 +00:00
b77e6f0c98 clutter: Content: Use G_DECLARE_INTERFACE()
It cuts away a bit of the GObject boilerplate, gives us support for
`g_autoptr`, and removes the typedef hack inside clutter-content.c.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/380
2019-02-27 16:44:24 +00:00
b67394dcd1 clutter: StageWindow: Use G_DECLARE_INTERFACE()
It cuts away a bit of the GObject boilerplate, gives us support for
`g_autoptr`, and removes the typedef hack inside clutter-stage-window.c.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/380
2019-02-27 16:44:24 +00:00
f9e33a89fd clutter: cleanup/remove core input X11 backend
We don't use the core input X11 backend, remove it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/459
2019-02-27 12:07:24 +01:00
39e9e53871 clutter: Remove the rest of deprecated/clutter-animator.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
7f3fda6df6 clutter: Simplify clutter_state_change
clutter_state_get_animator now always returns NULL, because
_set_animator is never called.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
73ce5b3a8d clutter: Remove tests/interactive/test-state-animator.c
This is the only caller of the (deprecated) clutter_state_set_animator.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
53319a121f clutter: Remove unused deprecated code from clutter-actor-deprecated.c
Since clutter_actor_set_shader() is never called, none of this has any
effect.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
cf2d06e9b9 clutter: Remove deprecated clutter-score.c
https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
d39211f438 clutter: Remove deprecated clutter_egl{,x}_display
https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
909464f749 clutter: Remove deprecated XInput code
https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
5669b64021 clutter: Remove unused clutter-glx-texture-pixmap.c and friends
https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
8f0b4767de clutter: Remove deprecated clutter_x11_get_stage_visual
https://gitlab.gnome.org/GNOME/mutter/merge_requests/452
2019-02-27 03:32:21 +00:00
9e75ce2ad7 monitor-config-store: Read system wide config files
Before introducing the new config store, the old monitor configuration
system read system wide monitor configuration files. Add back that
feature.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/253
2019-02-26 21:04:27 +00:00
c010a3b195 Update German translation 2019-02-26 19:44:02 +00:00
7c807c6e2a org.gnome.Mutter.ScreenCast: Document what was added in API version 2
RecordWindow and the cursor-mode property are only available if the
advertised version is at least 2.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
9a20271f90 screen-cast-window-stream: Add support for cursor modes
Make the RecordWindow method also understand the 'cursor-mode' property.
For 'embedded' the cursor is drawn onto the pixel buffer using cairo,
otherwise it works similarly to how RecordMonitor deals with it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
1760a6e560 screen-cast: Bump API version to 2
https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
8c2b805d88 screen-cast-src: Add helper to draw cursor sprite into pixel buffer
It makes sure the cursor sprite is correctly scaled and positioned in
stream coordinate space.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
2f01418d45 screen-cast-window: Add API to check if content has damage
https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
a76107a19f screen-cast-window: Add API to transform cursor state
To be used to translate absolute cursor positions to relative positions,
as well as to determine whether a cursor sprite is inside the stream or
not. It also helps calculating the scale the cursor sprite needs to be
scaled with to be in stream coordinate space.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
6372e3e4db clutter: Add clutter_actor_has_damage() API
Will be used to check whether there are any damage to an actor.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
c80ba819e7 screen-cast-window-src: Keep a screen cast window instead of an actor
Practically it's the same object, but ideally, we should not deal
with "actors" anywhere here.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
14c6a347c1 screen-cast-window-src: Rename painted callback to after_paint
We'll add a before_paint soon, so better have the names somewhat match.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
11bd847896 screen-cast-window-stream: Don't set the position property
It was not meant to be set for window streams, and was set to (0, 0)
anyway. This removes the corresponding MetaScreenCastWindow API, as it's
not needed anymore.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
870f38542d screen-cast-window-stream: Set the size property to the logical size
As the stream size is the logical monitor size multiplied with the ceil
of the logical monitor scale, the corresponding logical size, which is
what should be passed via the size property on the D-Bus object, should
be the logical monitor size.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
c22edeff1f screen-cast-window-stream: Use initable to initialize
Move the initialization from _new() to an initable implementation. This
will allow us to initialize fields before MetaScreenCastStream
initializes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
183de60d91 screen-cast-src: Move back MetaSpaType to C file
It's not needed by the monitor source anymore.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
176b508029 screen-cast-src: Change offscreen cursor helper to take a uint8_t *
Instead of a `uint32_t *`. Eventually we shouldn't assume pixels are
always 32 bit, and this gets rid of some casts while at it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
9be189daa7 screen-cast: Move cursor metadata setting to generic source
Make the monitor implementation do things strictly related to its own
source type, leaving the Spa related logic and cursor read back in the
generic layer, later to be reused by the window source type
implementation.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/413
2019-02-26 13:39:11 +00:00
bf12a2497b clutter: Make docs match with signal description
Makes gobject-introspection happy again.

Pointed out by Robert Mader at:
https://gitlab.gnome.org/GNOME/mutter/merge_requests/196
2019-02-25 20:12:21 +01:00
55d168d01a clutter: Add ClutterPaintVolume argument to ClutterActor::queue_redraw
This is an ABI break, hopefully an unimportant one since this signal/vmethod
is barely overridden.

The signal has been added an extra ClutterPaintVolume argument, and has been
given a boolean return value. The recursion to the parents has been taken
out of the default implementation and into the caller, using the returned
boolean parameter to control further propagation.

Passing the ClutterPaintVolume is easier on performance, as we don't need
setting this pointer as gobject data just to retrieve/unset it further
in propagation.

https://bugzilla.gnome.org/show_bug.cgi?id=782344
2019-02-25 18:17:34 +00:00
8a9a78ec8a wayland: Check whether Xwayland window had a prior surface in generic code
Since commit 8df2a1452c (As pointed out by Robert Mader) we just happened
do this check when doing the first lookup for a Wayland surface for a
XWayland window, when we are later notifying upon surface creation we just
set the relation with no further checks.

The cases pointed out in the comment (eg. window changing decoration) might
presumably happen in a quick enough sequence that we have two scheduled
associations on the fly, so move this check to the more generic
meta_xwayland_associate_window_with_surface() which is called on both
immediate and delayed paths.

https://gitlab.gnome.org/GNOME/mutter/issues/361
2019-02-25 17:53:52 +00:00
803ffc19a4 shaped-texture: Clean-up deprecated NPOT check
There are most likely no GNOME users left still using hardware that
does not support NPOT textures. Further more, they would crash much
earlier and never hit this code-path. So remove the unnecessary check
here.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/447
2019-02-25 17:51:48 +01:00
ddd2ce3a88 wayland/buffer: Fall back to CoglTexture2DSliced
XWayland creates buffers of the combined size of all connected displays.
This can, especially on older but still in use hardware, exceed the limits
of the GPU.

If that is the case, use `CoglTexture2DSliced` instead of `CoglTexture2D`

https://gitlab.gnome.org/GNOME/mutter/merge_requests/447
2019-02-25 17:51:44 +01:00
979e689278 renderer/native: Retry page flip after one vsync if EBUSY
We might fail to page flip a new buffer, often after resuming, due to
the FIFO being full. Prior to this commit, we handled this by switching
over to plain mode setting instead of page flipping. This is bad because
we won't be synchronized to the refresh rate anymore, but just the
clock.

Instead, deal with this by trying again until the FIFO is no longer
full. Do this on a v-sync based interval, until it works.

This also changes the error handling code for drivers not supporting
page flipping to rely on them returning -EINVAL. The handling is moved
from pretending a page flip working to explicit mode setting in
meta-renderer-native.c.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/460
2019-02-25 15:48:29 +00:00
2c1ab8b3cc renderer/native: Remove legacy non-stage-view code
A renderer view will, under the native backend, since long ago always
have a logical monitor associated with it, so remove the code handling
the legacy non-stage view case.

https://gitlab.gnome.org/GNOME/mutter/issues/460
2019-02-25 15:48:29 +00:00
252e64a0ea wayland: Move surface texture ownership to MetaWaylandSurface
Prior to this commit, MetaWaylandSurface held a reference to
MetaWaylandBuffer, who owned the texture drawn by the surface. When
switching buffer, the texture change with it.

This is problematic when dealing with SHM buffer damage management, as
when having one texture per buffer, damaged regions uploaded to one,
will not follow along to the next one attached. It also wasted GPU
memory as there would be one texture per buffer, instead of one one
texture per surface.

Instead, move the texture ownership to MetaWaylandSurface, and have the
SHM buffer damage management update the surface texture. This ensures
damage is processed properly, and that we won't end up with stale
texture content when doing partial texture uploads. If the same SHM
buffer is attached to multiple surfaces, each surface will get their own
copy, and damage is tracked and uploaded separately.

Non-SHM types of buffers still has their own texture reference, as the
texture is just a representation of the GPU memory associated with the
buffer. When such a buffer is attached to a surface, instead the surface
just gets a reference to that texture, instead of a separately allocated
one.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-25 15:35:38 +00:00
d2f1edd6c6 wayland/surface: Process damage also for non-actor surfaces
The texture still needs to be updated with damaged content.

https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-25 15:35:38 +00:00
944a4763f6 cursor-renderer/native: Clear active CRTC gbm_bo when destroyed
When we freed the cursor GPU state including the gbm_bo objects attached
to it, we didn't unset the cursor renderer private of the CRTCs of the
associated GPU. This means that HW cursor invalidation could potentially
break if a new gbm_bo happened to be allocated at the same memory
address as the previous one.

To avoid this, iterate through the CRTCs of the GPU of which the cursor
data is freed, and unset the cursor renderer private if it was the one
destroyed.

https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-25 15:35:38 +00:00
22a296f971 wayland/dma-buf: Don't use API meant for MetaWaylandSurface internally
What was actually done when calling meta_wayland_buffer_attach() was
that the texture was realized, so just call the function
`meta_wayland_dma_buf_realize_texture()` and call that.

This is in preparation to change how meta_wayland_buffer_attach() work.

https://gitlab.gnome.org/GNOME/mutter/issues/199
2019-02-25 15:35:38 +00:00
ef2153739c idle-monitor: Fix duplicate return value of ResetIdletime call
The signal handler must return TRUE as the invocation is already handled
by returning an error. Also update the error message a bit to clarify
that the API exists only for testing purposes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/457
2019-02-25 14:42:03 +00:00
9e1c8e2c22 Update Italian translation 2019-02-22 11:07:11 +00:00
fca0e6abb1 Bump version to 3.31.91
Update NEWS.
2019-02-21 19:45:43 +01:00
6975c8b424 monitor-config-manager: respect other outputs' CRTC
We should not only take the old CRTC for an output whenever
possible, but we should also assign one that is 'free', i.e.
one that another monitor (to be processed after this one)
isn't using, so that that monitor can use the same CRTC.

https://gitlab.gnome.org/GNOME/mutter/issues/373
2019-02-21 17:23:38 +02:00
f4f823f238 monitor-config-manager: reuse old CRTC when possible
We shouldn't change an output's CRTC if we don't have to, as
that causes the output to go black.

This patch depends on
"monitor-unit-tests: initial crtcs in custom_lid_switch".

https://gitlab.gnome.org/GNOME/mutter/issues/373
2019-02-21 17:23:38 +02:00
1c67260bd4 monitor-unit-tests: initial crtcs in custom_lid_switch
This test forgot to specify the existing CRTC routings in the setup. For the
first output the default 0 was ok, now it is -1 to ensure that the code will
assign it correctly. For the second output the default 0 was incorrect, because
possible_crtcs does not include 0.  Now that CRTC is initialized to off
instead, because the second output is hotplugged later and running a CRTC
without an output does not make sense.

This fix will keep this test passing when a future patch attempts to preserve
existing CRTC routings. Assuming that any existing routing is valid, such
routing will be kept. In this test case the existing routing was illegal, it
should have been impossible, which then causes that future patch to fail the
test by assigning the wrong CRTC.

https://gitlab.gnome.org/GNOME/mutter/issues/373
2019-02-21 17:22:12 +02:00
79f90c147c MetaPluginManager: Don't return void value
The spec for `meta_plugin_manager_confirm_display_change()` is to return
`void`, no need to return a value there.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/456
2019-02-21 09:31:15 +01:00
4e751a3b58 Update Brazilian Portuguese translation 2019-02-21 01:12:00 +00:00
1c2e8fcf06 keybinding: Store flags in MetaKeyGrab
The external grab handler is shared across all external bindings and external
bindings have now different binding flags. For this reason, when rebuilding the
binding table there could be loss of information if we assign the bindings flags
of the external handler to all external bindings. Let's store the bindings flags
in MetaKeyGrab too and use this when rebuilding the binding table to avoid the
above issue.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/169
2019-02-20 14:36:24 +00:00
00ca387ec7 keybindings: Add flag param to grab_accelerator
Add a 'flags' parameters to meta_display_grab_accelerator. This will allow
e.g. gnome-settings-daemon (through the gnome-shell's GrabAccelerator API) to
create shorcuts that should descard auto-repeated key events.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/169

Closes: https://gitlab.gnome.org/GNOME/gnome-settings-daemon/issues/68
2019-02-20 14:36:24 +00:00
5688f1cf6e Updated Spanish translation 2019-02-20 15:34:11 +01:00
7bd668e6d0 window: Do not restore shortcuts on a NULL window
The "force restore shortcuts" being triggered by a key-combo, there is
no guarantee that the currently focused window is actually non-NULL in
which case we would crash.

Make sure there is a window currently focused before trying to restore
the shortcuts on that window.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/464
2019-02-18 11:23:59 +01:00
1dc602e289 Update Chinese (Taiwan) translation 2019-02-17 16:23:32 +00:00
ec518c4f24 Update Kazakh translation 2019-02-17 07:40:18 +00:00
0d9295523e clutter: Remove deprecate/clutter-frame-source.h
https://gitlab.gnome.org/GNOME/mutter/merge_requests/445
2019-02-15 23:01:01 +00:00
a4443885a3 clutter: Remove deprecated/clutter-timeout-pool.h
https://gitlab.gnome.org/GNOME/mutter/merge_requests/445
2019-02-15 23:01:01 +00:00
ef8f2876e3 clutter: Remove deprecated/clutter-backend.h
https://gitlab.gnome.org/GNOME/mutter/merge_requests/445
2019-02-15 23:01:01 +00:00
75071aba68 clutter: Remove deprecated/clutter-util.h
https://gitlab.gnome.org/GNOME/mutter/merge_requests/445
2019-02-15 23:01:01 +00:00
a81435ab5f cogl: Remove CoglBool, use gboolean instead
This basically reverts commit 54735dec, which tried to avoid the
GLib-defined types in favor the standard C ones. One exception to this
is the bool type, for which the commit introduces a new type CoglBool.

Let's just get rid of this type in favor of having consistency with the
GLib types. Note by the way that neither CoglBool nor gboolean (which
has a size of `int`) are completely compatible with bool (size `char`).

https://gitlab.gnome.org/GNOME/mutter/merge_requests/321
2019-02-15 16:35:46 +01:00
6fe46cac60 wayland/xdg-shell: Do not maximize if not possible
On X11, if a window cannot be maximized because its minimum size is
already larger than the output size, a request to maximize will be
ignored.

On Wayland, however, we would still honor the maximize request and
switch the window state to maximized, without actually moving the window
which leads to weird visual effects, as the window end up being
maximized in-place.

To avoid this, make sure the window has the maximize functionality
available prior to change its state in xdg-shell `set_maximized`
request.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/463
2019-02-15 09:40:44 +01:00
c3b9ef7bf5 gpu: Remove unimplemented ::get_kms_file_path()
https://gitlab.gnome.org/GNOME/mutter/merge_requests/444
2019-02-15 09:17:07 +01:00
b70c0eb9a5 gitlab-ci.yml: Add check for issue or MR URL
This adds a pipeline stage for merge requests that checks that the
commit message contains an URL to either a issue or a merge request.
This means that for merge requests without corresponding issues will
always fail initially, as the merge request URL is not known until after
it is created. This is still arguably better than accidentally merging
merge requests without URLs.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/440
2019-02-14 17:10:32 +01:00
f3dd97e67b README: Add contribution section
Short and incomplete blurb about coding style and commit message
guidelines.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/440
2019-02-14 15:38:46 +01:00
77fb0a0003 window-actor: Remove public declaration for get_x_window
meta_window_actor_get_x_window has been removed in commit 422648e2 but has not
been removed from the header for ages.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/439
2019-02-14 13:09:20 +00:00
58d2a674c4 window: Return focusable ability looking at properties only
As per commit 43633d6b, we mark an unmanaging window as not focusable, while
this is true, it might cause not resetting the current focused window when
unmanaging it causing a crash.

Also this wouldn't allow to check if a window can be focused when unmanaging it,
so let's revert the previous behavior.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/462
2019-02-14 13:49:51 +01:00
9e2ed4104d wayland: Reset text-input state after commit
This was wrongly done just before enable, which is not right as
per the protocol. A side effect was that input purpose/hints were
eagerly reset before being applied, thus not properly honored,
noticed in the doing of emoji/numeric OSK panels.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/410
2019-02-14 11:23:07 +01:00
3f9b4a1ab5 Updated Danish translation 2019-02-13 18:50:51 +01:00
2aa0ec004a Update Romanian translation 2019-02-13 15:02:51 +00:00
f798912cbd window: Move can_ping to a function and implement in X11
https://gitlab.gnome.org/GNOME/mutter/merge_requests/421
2019-02-13 02:07:41 +00:00
3bf80a967c window-x11: Move delete_window to MetaWindowX11Private
https://gitlab.gnome.org/GNOME/mutter/merge_requests/421
2019-02-13 02:07:41 +00:00
6c3b0cfc36 window-x11: Move take_focus to MetaWindowX11Private
https://gitlab.gnome.org/GNOME/mutter/merge_requests/421
2019-02-13 02:07:41 +00:00
43633d6b2f window: Add is_focusable class method
Implement is_focusable for both x11 and wayland and just use this check
so that we can abstract things more and be less dependent on window backend.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/421
2019-02-13 02:07:41 +00:00
fdd531f307 Updated Czech translation 2019-02-12 14:23:15 +01:00
70c45f8941 Updated Slovenian translation 2019-02-12 12:35:34 +01:00
b82fa2c610 meta-launcher: g_propagate_*_error takes ownership
This means we need to make sure we don't accidentally free the provided
source GError (which automatically happens with `g_autoptr`), so use
`g_steal_pointer()`.

This fixes an issue where, when launched in a bubblewrap environment
(such as the one provided by Buildstream), mutter would give the
following warning message:

```
mutter-WARNING **: 8:31:35:069: Can't initialize KMS backend: (null)
```

... which isn't that useful when trying to debug the actual issue.
2019-02-12 09:41:04 +01:00
eaacbb3289 gitlab-ci: Don't upload test artifacts
There's no need to upload test artifacts since they don't produce anything
that we care about so far, while this phase slows down the pipeline execution.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/436
2019-02-11 16:31:10 +01:00
54fdd633fe input-mapper: Use g_auto to free a string array
https://gitlab.gnome.org/GNOME/mutter/merge_requests/435
2019-02-11 15:42:16 +01:00
29ed84e921 input-mapper: Don't loop infinitely in EDID matching
Iterate over all the monitor product words to check for a partial matching on
EDID, otherwise we would hang inside an infinite while loop.

Fixes https://gitlab.gnome.org/GNOME/mutter/issues/459
2019-02-11 15:42:16 +01:00
d587fc1ef4 Update Swedish translation 2019-02-09 21:16:02 +00:00
285d717ceb Updated Lithuanian translation 2019-02-09 22:55:38 +02:00
616a149917 Update Turkish translation 2019-02-09 20:14:51 +00:00
f578c4daaa Update Galician translation 2019-02-09 15:34:22 +00:00
830495b7c6 Updated French translation 2019-02-09 12:21:14 +01:00
4d02f68057 Update French translation
Cherry-pick 28d2d54189 from gnome-3-30 branch.
2019-02-09 12:18:05 +01:00
31c5a0009f Update Finnish translation 2019-02-09 09:03:39 +00:00
c91d9df481 Bump version to 3.31.90
Update NEWS.
2019-02-07 01:22:26 +01:00
e64cbfcc3f Update Polish translation 2019-02-06 22:00:09 +01:00
3c2d85b544 Update Catalan translation 2019-02-06 20:56:26 +01:00
96c4dd817e Update Indonesian translation 2019-02-06 14:18:39 +00:00
ba7af4f7d3 wayland/surface: Add support for wp_viewporter
This adds the required bits to wayland surfaces and ties them up
to the compositor parts.

It is based on and very similar in nature to buffer transforms.

From the specification:
> The global interface exposing surface cropping and scaling
> capabilities is used to instantiate an interface extension for a
> wl_surface object. This extended interface will then allow cropping
> and scaling the surface contents, effectively disconnecting the
> direct relationship between the buffer and the surface size.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/323
2019-02-06 12:24:03 +00:00
edfe5cc3b7 shaped-texture: Add support for viewports
This implements the viewporter protocol which offers a cropping and scaling
capabilities to wayland clients.

There are several use cases for this, for example video players and games,
both as a convenience function and as potential performance optimization when
paired with hardware overlays etc.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/323
2019-02-06 12:24:02 +00:00
07e65a6ef2 region-utils: Add API to crop and scale an integer region
https://gitlab.gnome.org/GNOME/mutter/merge_requests/323
2019-02-06 12:24:02 +00:00
d574cf59f1 boxes: Add API to crop and scale a MetaRectangle
https://gitlab.gnome.org/GNOME/mutter/merge_requests/323
2019-02-06 12:24:02 +00:00
47402d848d Updated Spanish translation 2019-02-06 11:43:48 +01:00
922f14276a Update Hungarian translation 2019-02-05 20:07:46 +00:00
8c5ad7ea2d Update Friulian translation 2019-02-05 11:13:55 +00:00
20c5e2525e monitor-manager: Provide proper contexts for translators
Two strings were both "%s %s", but with different meaning. Let
translators know the difference by providing context using C_().
2019-02-04 18:41:05 +01:00
325fec31da monitor-manager: Add yet another wacky "physical dimension" 2019-02-04 17:41:36 +01:00
cbb2a286f2 monitor-manager: Don't use wacky physical dimensions in display name 2019-02-04 17:41:36 +01:00
e9eaa37401 monitor-manager: Use output name as display name in GetResources 2019-02-04 17:41:36 +01:00
dbe73c3296 meson: Do not install cogl config.env if installed tests are disabled
Until meson 0.50, setting the install parameter in 'configure_file' is ignored
if 'install_dir' is set. Then until mutter doesn't depend on such meson version
cogl_installed_tests_libexecdir should be empty unless have_installed_tests is
false, or this file will be installed anyway.

See https://github.com/mesonbuild/meson/issues/4160
2019-02-04 15:49:56 +00:00
b4ae6cdd62 Don't include potentially sensitive window titles in logs
For various error and warning messages, mutter includes a description of
the window, and that description includes a snippet of the title of the
window. Those snippets find their way into system logs, which then means
they can potentially find their way into bug reports and similar. Remove
the window title information to eliminate this potential privacy issue.
2019-02-03 06:32:14 +01:00
317414ab26 clutter/paint-nodes: Push/pop framebuffer
Unfortunately, many parts of GNOME Shell and Mutter and Clutter
still use the implicit Cogl1 API. As such, it as a transition
between the old and new APIs, it is important to keep the
implicit draw framebuffer updated.

ClutterRootNode does not keep it updated though, and it might
lead to problems when rendering offscreen textures.

Fix that by pushing and popping the root node framebuffer on
pre- and post-draw, respectively.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/405
2019-02-01 12:42:12 +00:00
b63e104561 clutter/paint-nodes: Expose ClutterRootNode
The ClutterRootNode paint node is theoretically the
top-most node of a paint nodes tree, except that we
are not in the point of having full rendering trees
in Clutter (all rendering performed by paint nodes
is still local and immediate).

When controlling the rendering tree, MetaShapedTexture
may need to paint into an offscreen framebuffer under
some circumstations.

Expose ClutterRootNode so that MetaShapedTexture can
use it to render to offscreen framebuffers.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/405
2019-02-01 12:42:12 +00:00
02b184bfd7 clutter/paint-node: Expose clutter_paint_node_paint()
When painting to an offscreen framebuffer, MetaShapedTexture will
need to have full control of the painting routines of paint nodes.
As such, expose clutter_paint_node_paint() to allow forcing a
paint nodes paint from MetaShapedTexture.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/405
2019-02-01 12:42:12 +00:00
d8c7583922 clutter/paint-node: Add multitexture API
The multitexture API is not a shortcut for multiple calls
to the single texture API. It is meant to wrap calls to
cogl_framebuffer_draw_multitexture_rectangle(), which
uses the passed texture coordinates at different layers of
the pipeline.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/405
2019-02-01 12:42:12 +00:00
25f36b3892 clutter/image: Also invalidate size
ClutterImage is a ClutterContent implementation that
has an internally managed CoglTexture. This texture
is recreated when new image data is set.

ClutterContent implementations may have control over
the allocation of the widgets they're attached to,
through CLUTTER_REQUEST_CONTENT_SIZE. On those cases,
if the new image data differs in size from the previous
data, it is important to notify those actors about the
size change. However, currently ClutterImage does not
notify them.

With the introduction of clutter_content_invalidate_size(),
it is possible to report the size changes to attached
actors.

Adapt ClutterImage to invalidate_size() when image data
has different sizes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/405
2019-02-01 12:42:12 +00:00
0f0b411f6e clutter/content: Add clutter_content_invalidate_size()
ClutterContent has the ability to dictate the layout of any
given actor, through the CLUTTER_REQUEST_CONTENT_SIZE request
mode.

However, there is no way for ClutterContent implementations
to notify their attached actors that the content size changed.

Add a new optional ClutterContent.invalidate_size() vfunc and
clutter_content_invalidate_size().

https://gitlab.gnome.org/GNOME/mutter/merge_requests/405
2019-02-01 12:42:12 +00:00
5a71ed4411 clutter-event: Correctly annotate some methods
https://gitlab.gnome.org/GNOME/mutter/merge_requests/181
2019-01-31 16:50:04 +00:00
de76074336 ui: Remove fallback app menu
The app menu is in the process of being retired[0], and the shell
stopped displaying it while applications are in the process of
dropping it. It therefore doesn't make sense to always show a
fallback menu in server-side decorations, applications that still
set the menu can rely on GTK+'s own fallback instead.

[0] https://gitlab.gnome.org/GNOME/Initiatives/wikis/App-Menu-Retirement

https://gitlab.gnome.org/GNOME/gnome-shell/issues/624
2019-01-30 18:39:42 +00:00
f63b69bb23 gitlab-ci: Define exported global variables once
Don't redefine XDG runtime and gsettings schema paths multiple times, just
export the variables once and reuse them.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/408
2019-01-30 19:16:46 +01:00
a54f9e835c gitlab-ci: Use runtime dir owned only by current user
https://gitlab.gnome.org/GNOME/mutter/merge_requests/408
2019-01-30 18:57:56 +01:00
7a941138de gitlab-ci: Use artifacts to keep built data and reuse in test
Make test to be dependent on build phase, saving artifacts for some time in
order to just run the tests without performing any rebuild.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/408
2019-01-30 18:55:51 +01:00
2c5404532b screen-cast-stream: Don't broadcast PipeWireStreamAdded signal
The helper function from gdbus-codegen broadcasts the signal emission,
but we really only care about sending it to the specific peer that
created the session. Thus, only emit the signal to the particular peer
that owns the session.

https://bugzilla.gnome.org/show_bug.cgi?id=784199
2019-01-30 17:14:47 +00:00
be259117f5 Update POTFILES.skip 2019-01-30 17:29:03 +01:00
6932b3cbb3 renderer/native: fix missing GPU copy egl ext error
If the extension is missing, the GPU copy path would not work. The code sets
the error, but forgets to return a failure. Fix this.

While adding the necessary return FALSE, also destroy the EGL context we just
created. Code refactoring shares the destroying code.

Found by reading code.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/416
2019-01-30 15:57:30 +02:00
b76bf20092 backends/native: Don't use software renderer for GPU copy
If the GPU copy path would use a software renderer, fall back to the CPU
copy path. The CPU copy path is possibly faster and avoids screen
corruption issues that were observed on an Intel Haswell desktop. The
corruption was likely due to texturing from an unfinished rendering or
memory caching issues.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/325
2019-01-30 15:12:57 +02:00
a62dbc6680 renderer/native: Debug print chosen secondary FB format
Print the pixel format chosen for an output on a secondary GPU for
debugging. Knowing the format can aid in debugging e.g. red/blue channel
swaps and CPU copy performance issues.

This adds a DRM format printing helper in meta-crtc-kms.h. This header
is included in most native backend files making it widely available,
while DRM formats are specific to the native backend. It could be shared
with Wayland bits, DRM format codes are used there too.

The helper makes the pixel format much more readable than a "%x".

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
442dcc7855 renderer/native: Valid formats for secondary dumb buffers
When setting up an output on a secondary GPU with the CPU copy mode,
allocate the dumb buffers with a DRM format that is advertised supported
instead of hardcoding a format.

Particularly, DisplayLink devices do not quite yet support the hardcoded
DRM_FORMAT_XBGR8888. The proprietary driver stack actually ignores the
format assuming it is DRM_FORMAT_XRGB8888 which results the display
having red and blue channels swapped. This patch fixes the color swap
right now, while taking advantage if the driver adds support for XBGR
later.

The preferred_formats ordering is somewhat arbitrary. Here it is written
from glReadPixels point of view, based on my benchmarks on Intel Haswell
Desktop machine. This ordering prefers the format that was hardcoded
before.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
23e7a0a099 crtc/kms: Add primary plane format list accessors
These functions allow inspecting which pixel formats a CRTC's primary
plane supports. Future patches will inspect the supported formats and
pick a framebuffer format accordingly instead of hardcoding a format.

The copy list function will be used to initialize a formats list, and
the supports format function will be used to intersect that list against
another CRTC's supported formats.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
7f2dbb6c44 crtc/kms: Document meta_crtc_kms_get_modifiers
It has some details that may not be obvious from the function signature.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
8a0d0ce987 crtc/kms: Add fallback primary plane formats
This avoids having to hardcode the same fallbacks elsewhere multiple
times when determining what formats might be suitable for a set of
CRTCs. The formats_modifiers hash table is now guaranteed to be
populated with at least something, so future code will not need to
handle it being empty.

The hardcoded fallback formats are a minimal set probably supported by
most hardware. XRGB8888 is the format that, according to ancient lore,
all DRM devices should support, especially if they don't have the
capability to advertise otherwise. Mutter also hardcodes XRGB8888 as the
GBM surface format, so it is already required on primary GPUs.

XBGR8888 matches the most common OpenGL format, sans alpha channel since
scanout hardware has not traditionally supported alpha. XBGR8888 is here
also because Mutter hardcodes that format for secondary GPU outputs when
using the CPU copy path.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
0789c3fb9f crtc/kms: Use plane formats if no IN_FORMATS
If the IN_FORMATS property is not found, copy the formats from the DRM
plane instead. This is the fallback for getting a list of formats the
primary plane supports when DRM universal planes capability is enabled.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
31d99c51cb crtc/kms: Remove unused field formats_prop_id
It was set but never used.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
30550ef688 crtc/kms: Parse and store IN_FORMATS in full
Rather than picking just one format, parse and store all the formats and
their modifiers.

This gives us a list of supported formats (and modifiers) on a CRTC
primary plane. Later I will be using this list to choose a framebuffer
format instead of hardcoding it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/341
2019-01-30 12:53:20 +00:00
b04cca9eab clutter/evdev: Set the backend keymap before using it
The device manager evdev assumes the keymap is set, so better set it
before its creation.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/451
Fixes: 6de81b051 "evdev: Implement ClutterKeymap"
2019-01-30 11:27:57 +01:00
e0fd7a6d05 clutter: Avoid redundant margin changes
When profiling gnome-shell it was found that one of the main triggers
of `clutter_actor_queue_relayout` during animations was
`clutter_actor_set_margin_internal` continuously setting the same
zero margins. That's obviously pointless and also expensive. So just
avoid redundant margin changes.

This helps to further improve performance in:
https://gitlab.gnome.org/GNOME/mutter/issues/233,
https://gitlab.gnome.org/GNOME/gnome-shell/issues/349

This change previously landed as 59acb3895 and then got reverted because
it was found to make gnome-shell#517 worse. However that bug now has a
proper fix and this branch isn't really directly related so is being
reproposed...
2019-01-30 09:25:50 +00:00
923751aa39 clutter: Add ClutterKeymap getter
It is fetched from the ClutterBackend so far.
2019-01-29 16:53:29 +01:00
6de81b0513 evdev: Implement ClutterKeymap
Just move the minimal bits to this ClutterKeymapEvdev object. Much
of the functionality of a keymap is spread along ClutterSeatEvdev,
ClutterDeviceManagerEvdev and ClutterVirtualInputDevice. Future
refactors are due here.

Also, ideally keymaps are per-seat objects (at least keyboard state
is). We don't expose much info about seats altogether outside the
evdev device manager implementation. We just poke the main seat at
places, but eventually seats should be public.
2019-01-29 16:53:29 +01:00
7ae698795e clutter: Add generic ClutterKeymap object
We thus far have similar objects/code internal to backends. Expose the
minimum API necessary to cater for gnome-shell as a generic object.
So far only the X11 backend has an actual GObject for it, and was made
to be a subclass right away.
2019-01-29 16:53:29 +01:00
72692b1144 clutter-box-layout: Use floats and assert on denormal numbers
`distribute_natural_allocation` expects an input >= 0 of type `gint`. In
`get_preferred_size_for_opposite_orientation` it is used with an unchecked
variable `size` of type `gfloat`, which in case it is `Infinity`, gets
passed on in the macro `MAX (0, size)`. `Infinity` becomes `G_MININT`
when implicitly casted to `gint` in `distribute_natural_allocation`,
triggering the assertion `extra_space >= 0`.

The resulting warning in the log is counter intuitive and not very
helpful.

Use `float` in `distribute_natural_allocation` instead of `gint` and
assert on denormal values so we can more easily identify bugs.

Additionally change some types while at it and add a even more
expressive warning referencing the actor at one point.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/375
2019-01-28 18:36:05 +01:00
177b4df217 wayland: Implement window activation and focus stealing prevention
This is done through gtk-shell ATM. If a window requests focus with
an invalid startup ID, just the demands-attention flag will be set.
The "did user interaction happen in between" checks are left to
meta_window_activate_full/meta_window_focus, by passing the timestamp
of the original launch request.
2019-01-26 18:07:03 +01:00
a08d7cf48a wayland: Update gtk-shell protocol to v3
This version has 2 new requests:
- gtk_shell1.notify_launch notifies the compositor that the requesting
  client shall launch another application. The given ID is expected to
  be unique.
- gtk_surface1.request_focus notifies the compositor that a surface
  requests focus due to it being activated. The given ID is passed to
  this process through undetermined means, if it corresponds with a
  current startup ID and there was no user interaction in between the
  surface will be focused, otherwise it will demand attention.
2019-01-26 18:07:03 +01:00
3fa6a92cc5 screen-cast: Fix monitor recording on HiDPI
It scaled the logical monitor rect with scale to get the stream
dimensions, but that is only valid when having
'scale-monitor-framebuffers' enabled. Even when it was, it didn't work
properly, as clutter_stage_capture_into() doesn't work properly with
scaled monitor framebuffers yet.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/415
2019-01-26 16:18:45 +00:00
d5a7bbd094 Fix builds with G_DISABLE_ASSERT
Commit 25f416c13d added additional compilation warnings, including
-Werror=return-type. There are several places where this results
in build failures if `g_assert_not_reached()` is disabled at compile
time and the compiler misses a return value.

https://gitlab.gnome.org/GNOME/mutter/issues/447
2019-01-25 09:43:06 +01:00
de41f3ea28 clutter: Fix builds with G_DISABLE_ASSERT
Commit 25f416c13d added additional compilation warnings, including
-Werror=return-type. There are several places where this results
in build failures if `g_assert_not_reached()` is disabled at compile
time and the compiler misses a return value.

https://gitlab.gnome.org/GNOME/mutter/issues/447
2019-01-25 09:43:06 +01:00
5c3ec27b4b cogl: Fix builds with G_DISABLE_ASSERT
Commit 25f416c13d added additional compilation warnings, including
-Werror=return-type. There are several places where this results
in build failures if `g_assert_not_reached()` is disabled at compile
time and the compiler misses a return value.

https://gitlab.gnome.org/GNOME/mutter/issues/447
2019-01-25 00:48:12 +01:00
8655bc5d8d clutter: Fix offscreen-effect painting of clones
`ClutterOffscreenEffect` had been getting the wrong bounding box in the
case of clones and descendents of clones, causing visibly incorrect
clipping. This was due to `clutter_actor_get_paint_box` only ever being
given the source actor during a paint (which is correct) and not the clone.
Even if we weren't painting a clone but an offscreened descendent of a
clone (like in gnome-shell's desktop zoom), we would get the wrong result.

Fortunately we don't need to know the actual clone/actor being painted so
don't need to call the problematic `clutter_actor_get_paint_box` at all.
The solution is to only keep untransformed rendering in the FBO and leave
the correct transformation for later. The correct clone/actor's
transformation is already set for us as the current cogl modelview matrix
by `clutter_actor_paint`.

Bonus optimization: This all means we don't need to keep `last_matrix_drawn`
or force a full repaint every time some part of the transformation changes.
Because the FBO contents are no longer affected by transformations. As it
should be. In other words, offscreen-effected actors can now move around
on screen without themselves being repainted.

Special thanks to Mai Lavelle for identifying the cause of the problem.

Fixes:
https://bugzilla.gnome.org/show_bug.cgi?id=789050,
https://bugzilla.gnome.org/show_bug.cgi?id=659523#c9,
https://gitlab.gnome.org/GNOME/mutter/issues/196,
https://gitlab.gnome.org/GNOME/mutter/issues/282,
https://gitlab.gnome.org/GNOME/gnome-shell/issues/387,
https://launchpad.net/bugs/1767648,
https://launchpad.net/bugs/1779615
2019-01-24 17:00:25 +00:00
2e53ce8e75 meta, startup-notification: Make type declarations public
Shell is using these, which was revealed by
1bbb5c8107 breaking its build when
generating its introspection due to meta_startup_notification_get_type()
not being found.

We keep the class structs private, so in practice MetaStartupSequence
and MetaBackend can't be derived from (the are semi-private).
2019-01-24 16:38:09 +00:00
2528a39781 gitlab-ci.yml: Change build step build type to debugoptimized
We will catch -Wmaybe-uninitialized errors this way.
2019-01-23 21:05:51 +00:00
e02fef8e2f meta: Hide libmutter symbols by default and selectively export them
Make meson link libmutter using -fvisibility=hidden, and introduce META_EXPORT
and META_EXPORT_TEST defines to mark a symbols as visible.
The TEST version is meant to be used to flag symbols that are only used
internally by mutter tests, but that should not be considered public API.

This allows us to be more precise in selecting what is exported and what is
not, without the need of a version-script file that would be more complicated
to maintain.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/395
2019-01-23 14:18:13 +01:00
e352011830 MonitorManager: Use composition instead of inheriting from dbus skeleton
MonitorManager was inheriting from MetaDBusDisplayConfigSkeleton, this was
causing introspection to see this like a GDBus skeleton object exposing to
clients methods that were not required.

Also, this required us to export meta_dbus_* symbols to the library, while
these should be actually private.

So, make MetaMonitorManager to be just a simple GObject holding a skeleton
instance, and connect to its signals reusing most of the code with just few
minor changes.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/395
2019-01-23 14:12:07 +01:00
7f551ba776 meson: Don't list libraries private dependencies in pc files
pkg-config files for mutter are generated using *_pkg_deps as requires, but
programs linked with libmutter doesn't need most of these private dependencies
which are only needed for building and linking mutter and its subprojects.

So list packages needed only by mutter itself inside *_pkg_private_deps and
don't expose such packages to pkg-config, but only use them at build time.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3955
2019-01-23 13:03:40 +00:00
3838341d83 meson: Set cogl as dependency of libmutter-cogl dependency
Since a libmutter-cogl dependency is declared as libmutter_cogl_dep, it can be
used to avoid repeating cogl dependency everywhere.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3955
2019-01-23 13:03:40 +00:00
adc5670ea9 meson: Hide symbols by default in clutter
Clutter exports symbols explicitly using `CLUTTER_EXPORT`, so everything should
be hidden by default, unless exposed.

Usage of `gnu_symbol_visibility` needs a version bump to meson 0.48.0

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3955
2019-01-23 13:03:40 +00:00
08130912f0 meson: Set proper soversion and version to libraries
Soname of the libraries should be the major version number, while the version
triplet is currently used:
  objdump -p libmutter-4.so.0.0.0 | grep SONAME
    SONAME               libmutter-4.so.0.0.0

While is expected to be only libmutter-4.so.0

Fix all shared libraries by setting valid version and soversion.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/3955
2019-01-23 13:03:40 +00:00
371b97af27 meson: Fix map files and load them to hide private symbols
Map files were using wrong syntax (missing final `;` or invalid chars).

Also, the map files were only monitored for rebuilding, but not really used by
ld, so pass the ldflags with version-script so that private symbols are really
hidden.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/395
2019-01-23 13:03:40 +00:00
562cf14258 core: Fix compiler warning
Fix compiler warning: ‘startup_id’ may be used uninitialized in
`meta_launch_context_get_startup_notify_id()`.

Also change `gchar` to plain `char` while at it.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/406
2019-01-23 10:06:30 +01:00
c57ae7fc9c cogl/path: Don't depend on GL/glu.h
It's not needed for anything, and we can get rid of the dependency we
just added.

Also remove the installation step from Dockerfile.
2019-01-22 19:06:14 +01:00
6c91683380 gitlab-ci.yml: Treat warnings as errors
This'll allow us to catch them before they land.
2019-01-22 18:32:28 +01:00
25f416c13d meson.build: Add more compilation warnings
So that we can catch more issues. The warning list is copied from GTK+,
with two switch related ones removed.
2019-01-22 18:32:28 +01:00
8d91135926 wayland/xdg-shell: Fix buffer attach coordinate comparison
Only x was checked, but twice. Should check both x and y.
2019-01-22 18:32:28 +01:00
1bbb5c8107 meta: Only declare types when generating gir files
Some types were declared in the public headers so that g-ir-scanner
could resolve the types. This caused warnings when using
-Wredundant-decls, so only redeclare them for the gir scanner.
2019-01-22 18:32:28 +01:00
12a42a9295 wayland: Move DND surface role into its own file
This avoids a -Wredundand-decls warning about the get_type() function.
2019-01-22 18:32:28 +01:00
01cea0d9ef Fix const qualifier usage
As with the commits earlier, this also adds const qualifiers where
expected. However, the const variables are casted to non-const variants
so they can be passed to glib functions that take non-const variants but
expect const-like input.
2019-01-22 18:31:53 +01:00
f615eea7ee backend: Remove redundant function declarations 2019-01-22 18:31:52 +01:00
cbbd3e366a clutter/build: Don't pass --prototypes to glib-genmarshal
This causes compilation warnings and the prototypes are declared in the
header file already.
2019-01-22 18:31:52 +01:00
ede10dded0 clutter: Add missing void to function declaration 2019-01-22 18:31:52 +01:00
982d135ace cogl: Add missing function declarations
In plenty of places a non-static function was defined but didn't have
the corresponding declaration. Fix this by adding them, or alternatively
making them static.
2019-01-22 18:31:52 +01:00
548c0f16f4 cogl: Remove redundant function declarations 2019-01-22 18:31:52 +01:00
bbd295ae09 cogl: Fix const qualifier usage 2019-01-22 18:31:52 +01:00
c55004864d cogl: Add missing void to functions with no arguments
I.e. foo () -> foo (void).
2019-01-22 18:31:52 +01:00
54685091f1 cogl-path: Remove own glu.h version
cogl-path uses types from glu.h, but to avoid a build dependency on glu,
it kept a minified copy of glu.h in tree. Drop this file and just use
the actual glu.h. To avoid linking to libGLU.so, just use the
includepath, instead of actually adding glu as a real dependency.

This means we can remove an includepath meant to make it possible to
include <GL/glu.h>.
2019-01-22 18:31:52 +01:00
d4a9535f04 cogl-path: Cast function pointer explicitly
gluTessCallback() expects an equivalent to a GFunc, but we pass
functions with arguments without casting. To get rid of warnings, cast
the callback function pointer to the expected type.
2019-01-22 18:31:52 +01:00
44477390a9 clutter: Fix const qualifier usage
The const qualifiers were implicitly discarded here and there. Avoid that
either by adding the constness, or casting it away when a const variable
is passed to a function that is defined as non-const but effectively
expect a const.
2019-01-22 18:31:19 +01:00
caf27c4c16 clutter/tests: Remove dead code
Defined, but not used anywhere.
2019-01-22 18:31:19 +01:00
576e7a43df clutter/tests: Fix missing declaration warnings 2019-01-22 18:31:19 +01:00
c242558398 clutter/debug: Add printf annotations to log helpers 2019-01-22 18:31:19 +01:00
8c9e827aab clutter/stage: Fix debug logging
We expected %d but passed %f in a couple of places.
2019-01-22 18:31:19 +01:00
2bcc9e2b86 clutter/tests/interactive: Remove dead code
It was hidden behind a macro that was never defined anywhere.
2019-01-22 18:31:19 +01:00
5c66afbf63 Dockerfile: Update gsettings-desktop-schemas copr URL
The old rpms had been cleaned out.
2019-01-22 18:31:19 +01:00
84aeb8f715 Dockerfile: Remove manual pipewire-0.2.5 upgrade
It's already in F29 stable.
2019-01-22 18:31:14 +01:00
3738579dd3 window-actor: Use actual image size for capture
Previously, the clipping rectangle passed to
`meta_surface_actor_get_image()` was updated with the actual texture
size, but recent changes in `meta_shaped_texture_get_image()` now keep
the caller's clipping rectangle unchanged.

The implementation of `meta_window_actor_capture_into()` was relying on
the old behavior of updating the passed clipping rectangle, but now that
it's kept unchanged, the actual clipping rectangle used to copy the data
is wrong, which causes either a distorded image or worse, a crash of
mutter.

Use the resulting cairo image size to copy the data instead of the
clipping rectangle to avoid the issue and get the expected size.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/442
2019-01-22 10:30:04 +01:00
1ca60f424a input-settings/x11: Only warn once about missing udev support
Otherwise we end up logging the same message everytime we enter this function,
flooding the logs and making it annoying to spot other entries.
2019-01-22 02:21:13 +01:00
693 changed files with 10610 additions and 23191 deletions

View File

@ -1,20 +1,44 @@
image: registry.gitlab.gnome.org/gnome/mutter/master:v1
stages:
- review
- build
- test
check-commit-log:
stage: review
script:
- ./.gitlab-ci/check-commit-log.sh
only:
- merge_requests
build-mutter:
stage: build
script:
- meson . build -Degl_device=true -Dwayland_eglstream=true
- meson . build -Dbuildtype=debugoptimized -Degl_device=true -Dwayland_eglstream=true --werror
- ninja -C build
- ninja -C build install
artifacts:
expire_in: 1 day
paths:
- build
only:
- merge_requests
- /^.*$/
test-mutter:
stage: test
dependencies:
- build-mutter
variables:
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
script:
- meson . build -Degl_device=true -Dwayland_eglstream=true
- ninja -C build
- glib-compile-schemas $PWD/build/data
- env XDG_RUNTIME_DIR=/tmp/ GSETTINGS_SCHEMA_DIR=$PWD/build/data dbus-run-session -- xvfb-run -s '+iglx -noreset' meson test -C build -t 10 --verbose --no-stdsplit --wrap catchsegv
- mkdir -m 700 $XDG_RUNTIME_DIR
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
- >
dbus-run-session -- xvfb-run -s '+iglx -noreset'
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --wrap catchsegv
only:
- merge_requests
- /^.*$/

View File

@ -11,10 +11,7 @@ RUN dnf -y update && dnf -y upgrade && \
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 && \
# Unpackaged versions
dnf install -y https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00836095-gsettings-desktop-schemas/gsettings-desktop-schemas-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00836095-gsettings-desktop-schemas/gsettings-desktop-schemas-devel-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm && \
# Packages not yet in stable
dnf install -y https://kojipkgs.fedoraproject.org//packages/pipewire/0.2.5/1.fc29/x86_64/pipewire-0.2.5-1.fc29.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/pipewire/0.2.5/1.fc29/x86_64/pipewire-devel-0.2.5-1.fc29.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/pipewire/0.2.5/1.fc29/x86_64/pipewire-libs-0.2.5-1.fc29.x86_64.rpm && \
dnf install -y https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00848426-gsettings-desktop-schemas/gsettings-desktop-schemas-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm https://copr-be.cloud.fedoraproject.org/results/jadahl/mutter-ci/fedora-29-x86_64/00848426-gsettings-desktop-schemas/gsettings-desktop-schemas-devel-3.30.1-1.20181206git918efdd69be53.fc29.x86_64.rpm && \
dnf install -y intltool redhat-rpm-config make && \
dnf clean all

31
.gitlab-ci/check-commit-log.sh Executable file
View File

@ -0,0 +1,31 @@
#!/usr/bin/env bash
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
echo Cannot review non-merge request
exit 1
fi
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commits=$(git log --format='format:%H' $branch_point..$CI_COMMIT_SHA)
if [ -z "$commits" ]; then
echo Commit range empty
exit 1
fi
function commit_message_has_url() {
commit=$1
commit_message=$(git show -s --format='format:%b' $commit)
echo "$commit_message" | grep -qe "\($CI_MERGE_REQUEST_PROJECT_URL/\(issues\|merge_requests\)/[0-9]\+\|https://bugzilla.gnome.org/show_bug.cgi?id=[0-9]\+\)"
return $?
}
for commit in $commits; do
if ! commit_message_has_url $commit; then
echo "Missing merge request or issue URL on commit $(echo $commit | cut -c -8)"
exit 1
fi
done

81
NEWS
View File

@ -1,3 +1,84 @@
3.32.0
======
* Fix deadlock when cancelling a theme sound [Andrea; !474]
* Stop swizzling BGRA buffers (bye-bye inverted colors in screenshots
and animations) [Carlos; !486]
Contributors:
Andrea Azzarone, Carlos Garnacho, Robert Mader
3.31.92
=======
* Fix flicker of apps that use multiple SHM buffers [Jonas Å.; #199]
* Don't disable page flips after temporary failues [Jonas Å.; #460]
* Improve redraw performance [Carlos; !196]
* Add cursor-mode support to window screencasting [Jonas Å.; !413]
* Add back support for system-wide monitor configurations [Jonas Å.; !253]
* Add fractional scaling support [Marco, Jonas Å.; !3]
* Consider remapped keys when guessing keycode from keysym [Andrea; #443]
* Stop turning on-screen-keyboard off on focus changes [Carlos; !432]
* Fix crashes [Robert, Carlos, Jonas D., Florian; !447, #361, !426, #479]
* Misc. bug fixes and cleanups [Benjamin, Adam, Olivier, Niels, Piotr; !457,
!452, !459, !380, !361, !461, !464, !471, !473, !463]
Contributors:
Jonas Ådahl, Andrea Azzarone, Benjamin Berg, Piotr Drąg, Jonas Dreßler,
Olivier Fourdan, Carlos Garnacho, Niels De Graef, Adam Jackson, Robert Mader,
Florian Müllner, Marco Trevisan (Treviño)
Translators:
Milo Casagrande [it], Tim Sabsch [de], Trần Ngọc Quân [vi],
Gwan-gyeong Mun [ko], Марко Костић [sr], Daniel Mustieles [es],
Rūdolfs Mazurs [lv], Nathan Follens [nl]
3.31.91
=======
* Fix infinite loop in EDID matching [Marco; #459]
* wayland: Don't resetin text-input state prematurely [Carlos; !410]
* wayland: Don't maximize windows if minimum size is too big [Olivier; #463]
* Fix crash when using "restore shortcuts" without focus window [Olivier; #464]
* Add flag parameter to grab accelerator API [Andrea; !169]
* Reuse old CRTC if possible to avoid flicker on hotplug [Pekka, Emilio; #373]
* Misc. bug fixes and cleanups [Marco, Jonas, Niels, Adam, Olivier; !436,
!421, #462, !439, !440, !444, !321, !445, !456]
Contributors:
Jonas Ådahl, Andrea Azzarone, Olivier Fourdan, Carlos Garnacho,
Niels De Graef, Adam Jackson, Emilio Pozuelo Monfort, Pekka Paalanen,
Marco Trevisan (Treviño)
Translators:
Jiri Grönroos [fi], Charles Monzat [fr], Claude Paroz [fr], Fran Dieguez [gl],
Emin Tufan Çetin [tr], Aurimas Černius [lt], Anders Jonsson [sv],
Matej Urbančič [sl], Marek Cernocky [cs], Daniel Șerbănescu [ro],
Alan Mortensen [da], Baurzhan Muftakhidinov [kk], Yi-Jyun Pan [zh_TW],
Daniel Mustieles [es], Rafael Fontenelle [pt_BR]
3.31.90
=======
* Fix support of extended characters in on-screen keyboard [Andrea; #109]
* Improve selection of the primary GPU [Pekka, Emilio; !271]
* Screen-cast cursor updates as PipeWire stream metadata [Jonas; !357]
* Fix rendering glitches in magnifier [Daniel; gnome-shell#387]
* Fix monitor recording on HiDPI [Jonas; !415]
* Honour secondary GPU supported pixel formats [Pekka; !341]
* Fall back to CPU copy path when using a software renderer [Emilio; !325]
* Remove fallback app menu [Florian; gnome-shell#624]
* wayland: Add support for viewporter protocol [Robert; !323]
* Misc. bug fixes and cleanups [Florian, Carlos, Olivier, Marco, Robert,
Daniel, Pekka, Jonas, Ole, Georges; !391, #335, #442, !406, !395, #447,
!375, gnome-shell#349, #451, !416, #784199, !408, !181, !405]
Contributors:
Jonas Ådahl, Andrea Azzarone, Ole Jørgen Brønner, Piotr Drąg, Olivier Fourdan,
Dariusz Gadomski, Carlos Garnacho, Antoine Jacoutot, Iain Lane, Robert Mader,
Emilio Pozuelo Monfort, Florian Müllner, Georges Basile Stavracas Neto,
Pekka Paalanen, Marco Trevisan (Treviño), Josh Triplett, Daniel van Vugt
Translators:
Fabio Tomat [fur], Balázs Úr [hu], Daniel Mustieles [es], Kukuh Syafaat [id],
Jordi Mas [ca], Piotr Drąg [pl]
3.31.4
======
* keybindings: Limit corner move to current monitor [Jānis; #320]

View File

@ -22,6 +22,20 @@ by Gala, elementary OS's window manager. It can also be run standalone, using
the command "mutter", but just running plain mutter is only intended for
debugging purposes.
## Contributing
To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter.
The coding style used is primarily the GNU flavor of the [GNOME coding
style](https://developer.gnome.org/programming-guidelines/stable/c-coding-style.html.en)
with some minor additions such as preferring `stdint.h` types over GLib
fundamental types, and a soft 80 character line limit. However, in general,
look at the file you're editing for inspiration.
Commit messages should follow the [GNOME commit message
guidelines](https://wiki.gnome.org/Git/CommitMessages). We require an URL
to either an issue or a merge request in each commit.
## License
Mutter is distributed under the terms of the GNU General Public License,

View File

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

View File

@ -5,6 +5,7 @@
#include "clutter-types.h"
#include "clutter-interval.h"
#include "clutter-private.h"
#include "clutter-actor-box-private.h"
/**
* clutter_actor_box_new:
@ -542,6 +543,78 @@ clutter_actor_box_set_size (ClutterActorBox *box,
box->y2 = box->y1 + height;
}
void
_clutter_actor_box_enlarge_for_effects (ClutterActorBox *box)
{
float width, height;
/* The aim here is that for a given rectangle defined with floating point
* coordinates we want to determine a stable quantized size in pixels
* that doesn't vary due to the original box's sub-pixel position.
*
* The reason this is important is because effects will use this
* API to determine the size of offscreen framebuffers and so for
* a fixed-size object that may be animated accross the screen we
* want to make sure that the stage paint-box has an equally stable
* size so that effects aren't made to continuously re-allocate
* a corresponding fbo.
*
* The other thing we consider is that the calculation of this box is
* subject to floating point precision issues that might be slightly
* different to the precision issues involved with actually painting the
* actor, which might result in painting slightly leaking outside the
* user's calculated paint-volume. For this we simply aim to pad out the
* paint-volume by at least half a pixel all the way around.
*/
width = box->x2 - box->x1;
height = box->y2 - box->y1;
width = CLUTTER_NEARBYINT (width);
height = CLUTTER_NEARBYINT (height);
/* XXX: NB the width/height may now be up to 0.5px too small so we
* must also pad by 0.25px all around to account for this. In total we
* must padd by at least 0.75px around all sides. */
/* XXX: The furthest that we can overshoot the bottom right corner by
* here is 1.75px in total if you consider that the 0.75 padding could
* just cross an integer boundary and so ceil will effectively add 1.
*/
box->x2 = ceilf (box->x2 + 0.75);
box->y2 = ceilf (box->y2 + 0.75);
/* Now we redefine the top-left relative to the bottom right based on the
* rounded width/height determined above + a constant so that the overall
* size of the box will be stable and not dependant on the box's
* position.
*
* Adding 3px to the width/height will ensure we cover the maximum of
* 1.75px padding on the bottom/right and still ensure we have > 0.75px
* padding on the top/left.
*/
box->x1 = box->x2 - width - 3;
box->y1 = box->y2 - height - 3;
}
/**
* clutter_actor_box_scale:
* @box: a #ClutterActorBox
* @scale: scale factor for resizing this box
*
* Rescale the @box by provided @scale factor.
*
* Since: 1.6
*/
void
clutter_actor_box_scale (ClutterActorBox *box,
gfloat scale)
{
g_return_if_fail (box != NULL);
box->x1 *= scale;
box->x2 *= scale;
box->y1 *= scale;
box->y2 *= scale;
}
G_DEFINE_BOXED_TYPE_WITH_CODE (ClutterActorBox, clutter_actor_box,
clutter_actor_box_copy,
clutter_actor_box_free,

View File

@ -53,7 +53,8 @@ typedef enum
* Controls some options for how clutter_actor_traverse() iterates
* through the graph.
*/
typedef enum {
typedef enum
{
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST = 1L<<0,
CLUTTER_ACTOR_TRAVERSE_BREADTH_FIRST = 1L<<1
} ClutterActorTraverseFlags;
@ -74,7 +75,8 @@ typedef enum {
* the continuing traversal. It may stop traversal completely, just
* skip over children for the current actor or continue as normal.
*/
typedef enum {
typedef enum
{
CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE = 1L<<0,
CLUTTER_ACTOR_TRAVERSE_VISIT_SKIP_CHILDREN = 1L<<1,
CLUTTER_ACTOR_TRAVERSE_VISIT_BREAK = 1L<<2
@ -283,9 +285,6 @@ void _clutter_actor_queue_redraw_full
const ClutterPaintVolume *volume,
ClutterEffect *effect);
ClutterPaintVolume * _clutter_actor_get_queue_redraw_clip (ClutterActor *self);
void _clutter_actor_set_queue_redraw_clip (ClutterActor *self,
ClutterPaintVolume *clip_volume);
void _clutter_actor_finish_queue_redraw (ClutterActor *self,
ClutterPaintVolume *clip);
@ -316,8 +315,11 @@ void _clutter_actor_detach_clone
void _clutter_actor_queue_redraw_on_clones (ClutterActor *actor);
void _clutter_actor_queue_relayout_on_clones (ClutterActor *actor);
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
void _clutter_actor_queue_update_resource_scale_recursive (ClutterActor *actor);
CoglFramebuffer * _clutter_actor_get_active_framebuffer (ClutterActor *actor);
gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
float *resource_scale);
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
CoglTexture *texture);

View File

@ -635,6 +635,7 @@
#include "clutter-interval.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-mutter.h"
#include "clutter-paint-nodes.h"
#include "clutter-paint-node-private.h"
#include "clutter-paint-volume-private.h"
@ -655,7 +656,8 @@
* which indicates when to do something other than just enforce
* invariants.
*/
typedef enum {
typedef enum
{
MAP_STATE_CHECK, /* just enforce invariants. */
MAP_STATE_MAKE_UNREALIZED, /* force unrealize, ignoring invariants,
* used when about to unparent.
@ -697,6 +699,8 @@ struct _ClutterActorPrivate
/* the cached transformation matrix; see apply_transform() */
CoglMatrix transform;
float resource_scale;
guint8 opacity;
gint opacity_override;
@ -842,6 +846,7 @@ struct _ClutterActorPrivate
guint needs_y_expand : 1;
guint needs_paint_volume_update : 1;
guint had_effects_on_last_paint_volume_update : 1;
guint needs_compute_resource_scale : 1;
};
enum
@ -914,6 +919,7 @@ enum
PROP_SCALE_CENTER_X, /* XXX:2.0 remove */
PROP_SCALE_CENTER_Y, /* XXX:2.0 remove */
PROP_SCALE_GRAVITY, /* XXX:2.0 remove */
PROP_RESOURCE_SCALE,
PROP_ROTATION_ANGLE_X, /* XXX:2.0 rename to rotation-x */
PROP_ROTATION_ANGLE_Y, /* XXX:2.0 rename to rotation-y */
@ -1022,7 +1028,7 @@ typedef struct _TransitionClosure
static void clutter_container_iface_init (ClutterContainerIface *iface);
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
static void clutter_animatable_iface_init (ClutterAnimatableInterface *iface);
static void atk_implementor_iface_init (AtkImplementorIface *iface);
/* These setters are all static for now, maybe they should be in the
@ -1093,6 +1099,8 @@ static void clutter_actor_set_child_transform_internal (ClutterActor *sel
static void clutter_actor_realize_internal (ClutterActor *self);
static void clutter_actor_unrealize_internal (ClutterActor *self);
static gboolean clutter_actor_update_resource_scale (ClutterActor *self);
static void clutter_actor_ensure_resource_scale (ClutterActor *self);
static void clutter_actor_push_in_cloned_branch (ClutterActor *self,
gulong count);
@ -1108,7 +1116,6 @@ static void clutter_actor_pop_in_cloned_branch (ClutterActor *self,
{ _transform; } \
cogl_matrix_translate ((m), -_tx, -_ty, -_tz); } G_STMT_END
static GQuark quark_shader_data = 0;
static GQuark quark_actor_layout_info = 0;
static GQuark quark_actor_transform_info = 0;
static GQuark quark_actor_animation_info = 0;
@ -1520,6 +1527,8 @@ clutter_actor_real_map (ClutterActor *self)
priv->pick_id,
_clutter_actor_get_debug_name (self));
clutter_actor_ensure_resource_scale (self);
/* notify on parent mapped before potentially mapping
* children, so apps see a top-down notification.
*/
@ -2689,9 +2698,12 @@ clutter_actor_real_allocate (ClutterActor *self,
}
static void
_clutter_actor_signal_queue_redraw (ClutterActor *self,
ClutterActor *origin)
_clutter_actor_propagate_queue_redraw (ClutterActor *self,
ClutterActor *origin,
ClutterPaintVolume *pv)
{
gboolean stop = FALSE;
/* no point in queuing a redraw on a destroyed actor */
if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
return;
@ -2700,27 +2712,33 @@ _clutter_actor_signal_queue_redraw (ClutterActor *self,
* the actor bas been cloned. In this case the clone will need to
* receive the signal so it can queue its own redraw.
*/
while (self)
{
_clutter_actor_queue_redraw_on_clones (self);
_clutter_actor_queue_redraw_on_clones (self);
/* calls klass->queue_redraw in default handler */
if (g_signal_has_handler_pending (self, actor_signals[QUEUE_REDRAW],
/* calls klass->queue_redraw in default handler */
if (g_signal_has_handler_pending (self, actor_signals[QUEUE_REDRAW],
0, TRUE))
{
g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin);
}
else
{
CLUTTER_ACTOR_GET_CLASS (self)->queue_redraw (self, origin);
{
g_signal_emit (self, actor_signals[QUEUE_REDRAW], 0, origin, pv, &stop);
}
else
{
stop = CLUTTER_ACTOR_GET_CLASS (self)->queue_redraw (self, origin, pv);
}
if (stop)
break;
self = clutter_actor_get_parent (self);
}
}
static void
clutter_actor_real_queue_redraw (ClutterActor *self,
ClutterActor *origin)
static gboolean
clutter_actor_real_queue_redraw (ClutterActor *self,
ClutterActor *origin,
ClutterPaintVolume *paint_volume)
{
ClutterActor *parent;
CLUTTER_NOTE (PAINT, "Redraw queued on '%s' (from: '%s')",
_clutter_actor_get_debug_name (self),
origin != NULL ? _clutter_actor_get_debug_name (origin)
@ -2728,7 +2746,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
/* no point in queuing a redraw on a destroyed actor */
if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
return;
return TRUE;
/* If the queue redraw is coming from a child then the actor has
become dirty and any queued effect is no longer valid */
@ -2743,7 +2761,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
* won't change so we don't have to propagate up the hierarchy.
*/
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
return;
return TRUE;
/* Although we could determine here that a full stage redraw
* has already been queued and immediately bail out, we actually
@ -2757,7 +2775,7 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
if (stage != NULL &&
_clutter_stage_has_full_redraw_queued (CLUTTER_STAGE (stage)))
return;
return TRUE;
}
self->priv->propagated_one_redraw = TRUE;
@ -2765,12 +2783,17 @@ clutter_actor_real_queue_redraw (ClutterActor *self,
/* notify parents, if they are all visible eventually we'll
* queue redraw on the stage, which queues the redraw idle.
*/
parent = clutter_actor_get_parent (self);
if (parent != NULL)
{
/* this will go up recursively */
_clutter_actor_signal_queue_redraw (parent, origin);
}
return FALSE;
}
static inline gboolean
clutter_actor_needs_relayout (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
return (priv->needs_width_request ||
priv->needs_height_request ||
priv->needs_allocation);
}
static void
@ -3561,12 +3584,6 @@ _clutter_actor_update_last_paint_volume (ClutterActor *self)
priv->last_paint_volume_valid = TRUE;
}
static inline gboolean
actor_has_shader_data (ClutterActor *self)
{
return g_object_get_qdata (G_OBJECT (self), quark_shader_data) != NULL;
}
guint32
_clutter_actor_get_pick_id (ClutterActor *self)
{
@ -3740,7 +3757,7 @@ clutter_actor_paint_node (ClutterActor *actor,
if (!clutter_stage_get_no_clear_hint (CLUTTER_STAGE (actor)))
clear_flags |= COGL_BUFFER_BIT_COLOR;
node = _clutter_root_node_new (fb, &bg_color, clear_flags);
node = clutter_root_node_new (fb, &bg_color, clear_flags);
clutter_paint_node_set_name (node, "stageClear");
clutter_paint_node_add_rectangle (node, &box);
clutter_paint_node_add_child (root, node);
@ -3779,7 +3796,7 @@ clutter_actor_paint_node (ClutterActor *actor,
}
#endif /* CLUTTER_ENABLE_DEBUG */
_clutter_paint_node_paint (root);
clutter_paint_node_paint (root);
return TRUE;
}
@ -3808,7 +3825,6 @@ clutter_actor_paint (ClutterActor *self)
ClutterActorPrivate *priv;
ClutterPickMode pick_mode;
gboolean clip_set = FALSE;
gboolean shader_applied = FALSE;
ClutterStage *stage;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@ -3839,6 +3855,8 @@ clutter_actor_paint (ClutterActor *self)
if (!CLUTTER_ACTOR_IS_MAPPED (self))
return;
clutter_actor_ensure_resource_scale (self);
stage = (ClutterStage *) _clutter_actor_get_stage_internal (self);
/* mark that we are in the paint process */
@ -3978,25 +3996,13 @@ clutter_actor_paint (ClutterActor *self)
}
if (priv->effects == NULL)
{
if (pick_mode == CLUTTER_PICK_NONE &&
actor_has_shader_data (self))
{
_clutter_actor_shader_pre_paint (self, FALSE);
shader_applied = TRUE;
}
priv->next_effect_to_paint = NULL;
}
priv->next_effect_to_paint = NULL;
else
priv->next_effect_to_paint =
_clutter_meta_group_peek_metas (priv->effects);
clutter_actor_continue_paint (self);
if (shader_applied)
_clutter_actor_shader_post_paint (self);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_VOLUMES &&
pick_mode == CLUTTER_PICK_NONE))
_clutter_actor_draw_paint_volume (self);
@ -4216,7 +4222,8 @@ remove_child (ClutterActor *self,
child->priv->next_sibling = NULL;
}
typedef enum {
typedef enum
{
REMOVE_CHILD_DESTROY_META = 1 << 0,
REMOVE_CHILD_EMIT_PARENT_SET = 1 << 1,
REMOVE_CHILD_EMIT_ACTOR_REMOVED = 1 << 2,
@ -4352,7 +4359,10 @@ clutter_actor_remove_child_internal (ClutterActor *self,
/* clutter_actor_reparent() will emit ::parent-set for us */
if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child))
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
{
child->priv->needs_compute_resource_scale = TRUE;
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
}
/* if the child was mapped then we need to relayout ourselves to account
* for the removed child
@ -5677,6 +5687,16 @@ clutter_actor_get_property (GObject *object,
g_value_set_enum (value, clutter_actor_get_scale_gravity (actor));
break;
case PROP_RESOURCE_SCALE:
if (priv->needs_compute_resource_scale)
{
if (!clutter_actor_update_resource_scale (actor))
g_warning ("Getting invalid resource scale property");
}
g_value_set_float (value, priv->resource_scale);
break;
case PROP_REACTIVE:
g_value_set_boolean (value, clutter_actor_get_reactive (actor));
break;
@ -6337,7 +6357,6 @@ clutter_actor_class_init (ClutterActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
quark_shader_data = g_quark_from_static_string ("-clutter-actor-shader-data");
quark_actor_layout_info = g_quark_from_static_string ("-clutter-actor-layout-info");
quark_actor_transform_info = g_quark_from_static_string ("-clutter-actor-transform-info");
quark_actor_animation_info = g_quark_from_static_string ("-clutter-actor-animation-info");
@ -7131,6 +7150,19 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_PARAM_STATIC_STRINGS |
G_PARAM_DEPRECATED);
/**
* ClutterActor:resource-scale:
*
* The resource-scale of the #ClutterActor if any or -1 if not available
*/
obj_props[PROP_RESOURCE_SCALE] =
g_param_spec_float ("resource-scale",
P_("Resource Scale"),
P_("The Scaling factor for resources painting"),
-1.0f, G_MAXFLOAT,
1.0f,
CLUTTER_PARAM_READABLE);
/**
* ClutterActor:rotation-angle-x:
*
@ -8010,6 +8042,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
* ClutterActor::queue-redraw:
* @actor: the actor we're bubbling the redraw request through
* @origin: the actor which initiated the redraw request
* @volume: paint volume to redraw
*
* The ::queue_redraw signal is emitted when clutter_actor_queue_redraw()
* is called on @origin.
@ -8063,10 +8096,12 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_SIGNAL_RUN_LAST |
G_SIGNAL_NO_HOOKS,
G_STRUCT_OFFSET (ClutterActorClass, queue_redraw),
NULL, NULL,
_clutter_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
CLUTTER_TYPE_ACTOR);
g_signal_accumulator_true_handled,
NULL,
_clutter_marshal_BOOLEAN__OBJECT_BOXED,
G_TYPE_BOOLEAN, 2,
CLUTTER_TYPE_ACTOR,
CLUTTER_TYPE_PAINT_VOLUME);
/**
* ClutterActor::queue-relayout:
@ -8567,11 +8602,13 @@ clutter_actor_init (ClutterActor *self)
priv->opacity = 0xff;
priv->show_on_set_parent = TRUE;
priv->resource_scale = -1.0f;
priv->needs_width_request = TRUE;
priv->needs_height_request = TRUE;
priv->needs_allocation = TRUE;
priv->needs_paint_volume_update = TRUE;
priv->needs_compute_resource_scale = TRUE;
priv->cached_width_age = 1;
priv->cached_height_age = 1;
@ -8665,8 +8702,7 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self,
ClutterPaintVolume *clip)
{
ClutterActorPrivate *priv = self->priv;
ClutterPaintVolume *pv;
gboolean clipped;
ClutterPaintVolume *pv = NULL;
/* Remove queue entry early in the process, otherwise a new
queue_redraw() during signal handling could put back this
@ -8693,8 +8729,7 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self,
*/
if (clip)
{
_clutter_actor_set_queue_redraw_clip (self, clip);
clipped = TRUE;
pv = clip;
}
else if (G_LIKELY (priv->last_paint_volume_valid))
{
@ -8704,36 +8739,12 @@ _clutter_actor_finish_queue_redraw (ClutterActor *self,
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
/* make sure we redraw the actors old position... */
_clutter_actor_set_queue_redraw_clip (stage,
&priv->last_paint_volume);
_clutter_actor_signal_queue_redraw (stage, stage);
_clutter_actor_set_queue_redraw_clip (stage, NULL);
/* XXX: Ideally the redraw signal would take a clip volume
* argument, but that would be an ABI break. Until we can
* break the ABI we pass the argument out-of-band
*/
/* setup the clip for the actors new position... */
_clutter_actor_set_queue_redraw_clip (self, pv);
clipped = TRUE;
_clutter_actor_propagate_queue_redraw (stage, stage,
&priv->last_paint_volume);
}
else
clipped = FALSE;
}
else
clipped = FALSE;
_clutter_actor_signal_queue_redraw (self, self);
/* Just in case anyone is manually firing redraw signals without
* using the public queue_redraw() API we are careful to ensure that
* our out-of-band clip member is cleared before returning...
*
* Note: A NULL clip denotes a full-stage, un-clipped redraw
*/
if (G_LIKELY (clipped))
_clutter_actor_set_queue_redraw_clip (self, NULL);
_clutter_actor_propagate_queue_redraw (self, self, pv);
}
static void
@ -8893,8 +8904,7 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
{
/* NB: NULL denotes an undefined clip which will result in a
* full redraw... */
_clutter_actor_set_queue_redraw_clip (self, NULL);
_clutter_actor_signal_queue_redraw (self, self);
_clutter_actor_propagate_queue_redraw (self, self, NULL);
return;
}
@ -9558,6 +9568,8 @@ clutter_actor_get_preferred_width (ClutterActor *self,
return;
}
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_PREF_WIDTH);
/* the remaining cases are:
*
* - either min_width or natural_width have been set
@ -9649,6 +9661,8 @@ clutter_actor_get_preferred_width (ClutterActor *self,
if (natural_width_p)
*natural_width_p = request_natural_width;
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_PREF_WIDTH);
}
/**
@ -9702,6 +9716,8 @@ clutter_actor_get_preferred_height (ClutterActor *self,
return;
}
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_IN_PREF_HEIGHT);
/* the remaining cases are:
*
* - either min_height or natural_height have been set
@ -9792,6 +9808,8 @@ clutter_actor_get_preferred_height (ClutterActor *self,
if (natural_height_p)
*natural_height_p = request_natural_height;
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_PREF_HEIGHT);
}
/**
@ -10134,6 +10152,9 @@ clutter_actor_allocate (ClutterActor *self,
if (CLUTTER_ACTOR_IS_MAPPED (self))
self->priv->needs_paint_volume_update = TRUE;
if (stage_allocation_changed)
priv->needs_compute_resource_scale = TRUE;
if (!stage_allocation_changed)
{
/* If the actor didn't move but needs_allocation is set, we just
@ -12796,7 +12817,8 @@ typedef void (* ClutterActorAddChildFunc) (ClutterActor *parent,
ClutterActor *child,
gpointer data);
typedef enum {
typedef enum
{
ADD_CHILD_CREATE_META = 1 << 0,
ADD_CHILD_EMIT_PARENT_SET = 1 << 1,
ADD_CHILD_EMIT_ACTOR_ADDED = 1 << 2,
@ -12981,7 +13003,10 @@ clutter_actor_add_child_internal (ClutterActor *self,
/* clutter_actor_reparent() will emit ::parent-set for us */
if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child))
g_signal_emit (child, actor_signals[PARENT_SET], 0, NULL);
{
child->priv->needs_compute_resource_scale = TRUE;
g_signal_emit (child, actor_signals[PARENT_SET], 0, NULL);
}
if (check_state)
{
@ -13014,9 +13039,7 @@ clutter_actor_add_child_internal (ClutterActor *self,
/* maintain the invariant that if an actor needs layout,
* its parents do as well
*/
if (child->priv->needs_width_request ||
child->priv->needs_height_request ||
child->priv->needs_allocation)
if (clutter_actor_needs_relayout (child))
{
/* we work around the short-circuiting we do
* in clutter_actor_queue_relayout() since we
@ -13585,6 +13608,8 @@ clutter_actor_reparent (ClutterActor *self,
insert_child_at_depth,
NULL);
priv->needs_compute_resource_scale = TRUE;
/* we emit the ::parent-set signal once */
g_signal_emit (self, actor_signals[PARENT_SET], 0, old_parent);
@ -15159,7 +15184,7 @@ clutter_actor_set_final_state (ClutterAnimatable *animatable,
}
static void
clutter_animatable_iface_init (ClutterAnimatableIface *iface)
clutter_animatable_iface_init (ClutterAnimatableInterface *iface)
{
iface->find_property = clutter_actor_find_property;
iface->get_initial_state = clutter_actor_get_initial_state;
@ -16487,6 +16512,12 @@ clutter_actor_is_in_clone_paint (ClutterActor *self)
return FALSE;
}
gboolean
clutter_actor_has_damage (ClutterActor *actor)
{
return actor->priv->is_dirty;
}
static gboolean
set_direction_recursive (ClutterActor *actor,
gpointer user_data)
@ -16704,26 +16735,6 @@ clutter_actor_has_pointer (ClutterActor *self)
return self->priv->has_pointer;
}
/* XXX: This is a workaround for not being able to break the ABI of
* the QUEUE_REDRAW signal. It is an out-of-band argument. See
* clutter_actor_queue_clipped_redraw() for details.
*/
ClutterPaintVolume *
_clutter_actor_get_queue_redraw_clip (ClutterActor *self)
{
return g_object_get_data (G_OBJECT (self),
"-clutter-actor-queue-redraw-clip");
}
void
_clutter_actor_set_queue_redraw_clip (ClutterActor *self,
ClutterPaintVolume *clip)
{
g_object_set_data (G_OBJECT (self),
"-clutter-actor-queue-redraw-clip",
clip);
}
/**
* clutter_actor_has_allocation:
* @self: a #ClutterActor
@ -17768,6 +17779,171 @@ clutter_actor_get_paint_box (ClutterActor *self,
return TRUE;
}
static gboolean
_clutter_actor_get_resource_scale_for_rect (ClutterActor *self,
ClutterRect *bounding_rect,
float *resource_scale)
{
ClutterActor *stage;
float max_scale = 0;
stage = _clutter_actor_get_stage_internal (self);
if (!stage)
return FALSE;
if (!_clutter_stage_get_max_view_scale_factor_for_rect (CLUTTER_STAGE (stage),
bounding_rect,
&max_scale))
return FALSE;
*resource_scale = max_scale;
return TRUE;
}
static gboolean
_clutter_actor_compute_resource_scale (ClutterActor *self,
float *resource_scale)
{
ClutterRect bounding_rect;
ClutterActorPrivate *priv = self->priv;
if (CLUTTER_ACTOR_IN_DESTRUCTION (self) ||
CLUTTER_ACTOR_IN_PREF_SIZE (self) ||
!clutter_actor_is_mapped (self))
{
return FALSE;
}
clutter_actor_get_transformed_position (self,
&bounding_rect.origin.x,
&bounding_rect.origin.y);
clutter_actor_get_transformed_size (self,
&bounding_rect.size.width,
&bounding_rect.size.height);
if (bounding_rect.size.width == 0.0 ||
bounding_rect.size.height == 0.0 ||
!_clutter_actor_get_resource_scale_for_rect (self,
&bounding_rect,
resource_scale))
{
if (priv->parent)
return _clutter_actor_compute_resource_scale (priv->parent,
resource_scale);
else
return FALSE;
}
return TRUE;
}
static ClutterActorTraverseVisitFlags
queue_update_resource_scale_cb (ClutterActor *actor,
int depth,
void *user_data)
{
actor->priv->needs_compute_resource_scale = TRUE;
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
}
void
_clutter_actor_queue_update_resource_scale_recursive (ClutterActor *self)
{
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
queue_update_resource_scale_cb,
NULL,
NULL);
}
static gboolean
clutter_actor_update_resource_scale (ClutterActor *self)
{
ClutterActorPrivate *priv;
float resource_scale;
float old_resource_scale;
priv = self->priv;
g_return_val_if_fail (priv->needs_compute_resource_scale, FALSE);
old_resource_scale = priv->resource_scale;
priv->resource_scale = -1.0f;
if (_clutter_actor_compute_resource_scale (self, &resource_scale))
{
priv->resource_scale = resource_scale;
priv->needs_compute_resource_scale = FALSE;
return fabsf (old_resource_scale - resource_scale) > FLT_EPSILON;
}
return FALSE;
}
static void
clutter_actor_ensure_resource_scale (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
if (!priv->needs_compute_resource_scale)
return;
if (clutter_actor_update_resource_scale (self))
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_RESOURCE_SCALE]);
}
gboolean
_clutter_actor_get_real_resource_scale (ClutterActor *self,
gfloat *resource_scale)
{
ClutterActorPrivate *priv = self->priv;
clutter_actor_ensure_resource_scale (self);
if (!priv->needs_compute_resource_scale)
{
*resource_scale = priv->resource_scale;
return TRUE;
}
*resource_scale = -1.0f;
return FALSE;
}
/**
* clutter_actor_get_resource_scale:
* @self: A #ClutterActor
* @resource_scale: (out): return location for the resource scale
*
* Retrieves the resource scale for this actor, if available.
*
* The resource scale refers to the scale the actor should use for its resources.
* For example if an actor draws a a picture of size 100 x 100 in the stage
* coordinate space, it should use a texture of twice the size (i.e. 200 x 200)
* if the resource scale is 2.
*
* The resource scale is determined by calculating the highest #ClutterStageView
* scale the actor will get painted on.
*
* Returns: TRUE if resource scale is set for the actor, otherwise FALSE
*/
gboolean
clutter_actor_get_resource_scale (ClutterActor *self,
gfloat *resource_scale)
{
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
g_return_val_if_fail (resource_scale != NULL, FALSE);
if (_clutter_actor_get_real_resource_scale (self, resource_scale))
{
*resource_scale = ceilf (*resource_scale);
return TRUE;
}
return FALSE;
}
/**
* clutter_actor_has_overlaps:
* @self: A #ClutterActor
@ -18467,6 +18643,10 @@ clutter_actor_set_margin_top (ClutterActor *self,
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info_or_defaults (self);
if (info->margin.top == margin)
return;
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_TOP],
info->margin.top,
margin);
@ -18511,6 +18691,10 @@ clutter_actor_set_margin_bottom (ClutterActor *self,
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info_or_defaults (self);
if (info->margin.bottom == margin)
return;
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_BOTTOM],
info->margin.bottom,
margin);
@ -18555,6 +18739,10 @@ clutter_actor_set_margin_left (ClutterActor *self,
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info_or_defaults (self);
if (info->margin.left == margin)
return;
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_LEFT],
info->margin.left,
margin);
@ -18599,6 +18787,10 @@ clutter_actor_set_margin_right (ClutterActor *self,
g_return_if_fail (margin >= 0.f);
info = _clutter_actor_get_layout_info_or_defaults (self);
if (info->margin.right == margin)
return;
_clutter_actor_create_transition (self, obj_props[PROP_MARGIN_RIGHT],
info->margin.right,
margin);

View File

@ -236,8 +236,9 @@ struct _ClutterActorClass
void (* pick) (ClutterActor *actor,
const ClutterColor *color);
void (* queue_redraw) (ClutterActor *actor,
ClutterActor *leaf_that_queued);
gboolean (* queue_redraw) (ClutterActor *actor,
ClutterActor *leaf_that_queued,
ClutterPaintVolume *paint_volume);
/* size negotiation */
void (* get_preferred_width) (ClutterActor *self,
@ -583,6 +584,11 @@ gboolean clutter_actor_is_in_clone_paint
CLUTTER_EXPORT
gboolean clutter_actor_get_paint_box (ClutterActor *self,
ClutterActorBox *box);
CLUTTER_EXPORT
gboolean clutter_actor_get_resource_scale (ClutterActor *self,
gfloat *resource_scale);
CLUTTER_EXPORT
gboolean clutter_actor_has_overlaps (ClutterActor *self);

View File

@ -30,7 +30,7 @@
* to control how a #ClutterAnimation will animate a property.
*
* Each #ClutterAnimatable should implement the
* #ClutterAnimatableIface.interpolate_property() virtual function of the
* #ClutterAnimatableInterface.interpolate_property() virtual function of the
* interface to compute the animation state between two values of an interval
* depending on a progress factor, expressed as a floating point value.
*
@ -57,7 +57,6 @@
#include "deprecated/clutter-animatable.h"
#include "deprecated/clutter-animation.h"
typedef ClutterAnimatableIface ClutterAnimatableInterface;
G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
static void
@ -101,7 +100,7 @@ clutter_animatable_animate_property (ClutterAnimatable *animatable,
gdouble progress,
GValue *value)
{
ClutterAnimatableIface *iface;
ClutterAnimatableInterface *iface;
gboolean res;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
@ -155,7 +154,7 @@ GParamSpec *
clutter_animatable_find_property (ClutterAnimatable *animatable,
const gchar *property_name)
{
ClutterAnimatableIface *iface;
ClutterAnimatableInterface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
g_return_val_if_fail (property_name != NULL, NULL);
@ -185,7 +184,7 @@ clutter_animatable_get_initial_state (ClutterAnimatable *animatable,
const gchar *property_name,
GValue *value)
{
ClutterAnimatableIface *iface;
ClutterAnimatableInterface *iface;
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
g_return_if_fail (property_name != NULL);
@ -214,7 +213,7 @@ clutter_animatable_set_final_state (ClutterAnimatable *animatable,
const gchar *property_name,
const GValue *value)
{
ClutterAnimatableIface *iface;
ClutterAnimatableInterface *iface;
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
g_return_if_fail (property_name != NULL);
@ -260,7 +259,7 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
gdouble progress,
GValue *value)
{
ClutterAnimatableIface *iface;
ClutterAnimatableInterface *iface;
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
g_return_val_if_fail (property_name != NULL, FALSE);

View File

@ -33,24 +33,15 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ())
#define CLUTTER_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatable))
#define CLUTTER_IS_ANIMATABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATABLE))
#define CLUTTER_ANIMATABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_ANIMATABLE, ClutterAnimatableIface))
#define CLUTTER_TYPE_ANIMATABLE (clutter_animatable_get_type ())
typedef struct _ClutterAnimatableIface ClutterAnimatableIface;
CLUTTER_EXPORT
G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
CLUTTER, ANIMATABLE,
GObject)
/**
* ClutterAnimatable:
*
* #ClutterAnimatable is an opaque structure whose members cannot be directly
* accessed
*
* Since: 1.0
*/
/**
* ClutterAnimatableIface:
* ClutterAnimatableInterface:
* @animate_property: virtual function for custom interpolation of a
* property. This virtual function is deprecated
* @find_property: virtual function for retrieving the #GParamSpec of
@ -67,7 +58,7 @@ typedef struct _ClutterAnimatableIface ClutterAnimatableIface;
*
* Since: 1.0
*/
struct _ClutterAnimatableIface
struct _ClutterAnimatableInterface
{
/*< private >*/
GTypeInterface parent_iface;
@ -95,9 +86,6 @@ struct _ClutterAnimatableIface
GValue *value);
};
CLUTTER_EXPORT
GType clutter_animatable_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
GParamSpec *clutter_animatable_find_property (ClutterAnimatable *animatable,
const gchar *property_name);

View File

@ -34,7 +34,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActor, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAlignConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAnimatable, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindingPool, g_object_unref)
@ -49,7 +48,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClone, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColorizeEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContainer, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterContent, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeformEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDesaturateEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDeviceManager, g_object_unref)

View File

@ -24,6 +24,7 @@
#include <clutter/clutter-backend.h>
#include <clutter/clutter-device-manager.h>
#include <clutter/clutter-keymap.h>
#include <clutter/clutter-stage-window.h>
#include "clutter-event-translator.h"
@ -60,6 +61,8 @@ struct _ClutterBackend
GList *event_translators;
ClutterInputMethod *input_method;
ClutterKeymap *keymap;
};
struct _ClutterBackendClass
@ -104,6 +107,8 @@ struct _ClutterBackendClass
void (* bell_notify) (ClutterBackend *backend);
ClutterKeymap * (* get_keymap) (ClutterBackend *backend);
/* signals */
void (* resolution_changed) (ClutterBackend *backend);
void (* font_changed) (ClutterBackend *backend);
@ -155,8 +160,6 @@ void _clutter_backend_reset_cogl_framebuffer (Clutter
void clutter_set_allowed_drivers (const char *drivers);
void clutter_try_set_windowing_backend (const char *drivers);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */

View File

@ -53,9 +53,6 @@
#include "clutter-stage-window.h"
#include "clutter-device-manager-private.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-backend.h"
#ifdef CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT
#include "wayland/clutter-wayland-compositor.h"
#endif
@ -577,6 +574,18 @@ clutter_backend_real_get_device_manager (ClutterBackend *backend)
return backend->device_manager;
}
static ClutterKeymap *
clutter_backend_real_get_keymap (ClutterBackend *backend)
{
if (G_UNLIKELY (backend->keymap == NULL))
{
g_critical ("No keymap available, expect broken keyboard input");
return NULL;
}
return backend->keymap;
}
static gboolean
clutter_backend_real_translate_event (ClutterBackend *backend,
gpointer native,
@ -675,6 +684,7 @@ clutter_backend_class_init (ClutterBackendClass *klass)
klass->translate_event = clutter_backend_real_translate_event;
klass->create_context = clutter_backend_real_create_context;
klass->get_features = clutter_backend_real_get_features;
klass->get_keymap = clutter_backend_real_get_keymap;
}
static void
@ -890,129 +900,6 @@ clutter_get_default_backend (void)
return clutter_context->backend;
}
/**
* clutter_backend_set_double_click_time:
* @backend: a #ClutterBackend
* @msec: milliseconds between two button press events
*
* Sets the maximum time between two button press events, used to
* verify whether it's a double click event or not.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-time instead
*/
void
clutter_backend_set_double_click_time (ClutterBackend *backend,
guint msec)
{
ClutterSettings *settings = clutter_settings_get_default ();
g_object_set (settings, "double-click-time", msec, NULL);
}
/**
* clutter_backend_get_double_click_time:
* @backend: a #ClutterBackend
*
* Gets the maximum time between two button press events, as set
* by clutter_backend_set_double_click_time().
*
* Return value: a time in milliseconds
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-time instead
*/
guint
clutter_backend_get_double_click_time (ClutterBackend *backend)
{
ClutterSettings *settings = clutter_settings_get_default ();
gint retval;
g_object_get (settings, "double-click-time", &retval, NULL);
return retval;
}
/**
* clutter_backend_set_double_click_distance:
* @backend: a #ClutterBackend
* @distance: a distance, in pixels
*
* Sets the maximum distance used to verify a double click event.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-distance instead
*/
void
clutter_backend_set_double_click_distance (ClutterBackend *backend,
guint distance)
{
ClutterSettings *settings = clutter_settings_get_default ();
g_object_set (settings, "double-click-distance", distance, NULL);
}
/**
* clutter_backend_get_double_click_distance:
* @backend: a #ClutterBackend
*
* Retrieves the distance used to verify a double click event
*
* Return value: a distance, in pixels.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:double-click-distance instead
*/
guint
clutter_backend_get_double_click_distance (ClutterBackend *backend)
{
ClutterSettings *settings = clutter_settings_get_default ();
gint retval;
g_object_get (settings, "double-click-distance", &retval, NULL);
return retval;
}
/**
* clutter_backend_set_resolution:
* @backend: a #ClutterBackend
* @dpi: the resolution in "dots per inch" (Physical inches aren't
* actually involved; the terminology is conventional).
*
* Sets the resolution for font handling on the screen. This is a
* scale factor between points specified in a #PangoFontDescription
* and cairo units. The default value is 96, meaning that a 10 point
* font will be 13 units high. (10 * 96. / 72. = 13.3).
*
* Applications should never need to call this function.
*
* Since: 0.4
*
* Deprecated: 1.4: Use #ClutterSettings:font-dpi instead
*/
void
clutter_backend_set_resolution (ClutterBackend *backend,
gdouble dpi)
{
ClutterSettings *settings;
gint resolution;
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
if (dpi < 0)
resolution = -1;
else
resolution = dpi * 1024;
settings = clutter_settings_get_default ();
g_object_set (settings, "font-dpi", resolution, NULL);
}
/**
* clutter_backend_get_resolution:
* @backend: a #ClutterBackend
@ -1118,61 +1005,6 @@ clutter_backend_get_font_options (ClutterBackend *backend)
return backend->font_options;
}
/**
* clutter_backend_set_font_name:
* @backend: a #ClutterBackend
* @font_name: the name of the font
*
* Sets the default font to be used by Clutter. The @font_name string
* must either be %NULL, which means that the font name from the
* default #ClutterBackend will be used; or be something that can
* be parsed by the pango_font_description_from_string() function.
*
* Since: 1.0
*
* Deprecated: 1.4: Use #ClutterSettings:font-name instead
*/
void
clutter_backend_set_font_name (ClutterBackend *backend,
const gchar *font_name)
{
ClutterSettings *settings = clutter_settings_get_default ();
g_object_set (settings, "font-name", font_name, NULL);
}
/**
* clutter_backend_get_font_name:
* @backend: a #ClutterBackend
*
* Retrieves the default font name as set by
* clutter_backend_set_font_name().
*
* Return value: the font name for the backend. The returned string is
* owned by the #ClutterBackend and should never be modified or freed
*
* Since: 1.0
*
* Deprecated: 1.4: Use #ClutterSettings:font-name instead
*/
const gchar *
clutter_backend_get_font_name (ClutterBackend *backend)
{
ClutterSettings *settings;
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
settings = clutter_settings_get_default ();
/* XXX yuck. but we return a const pointer, so we need to
* store it in the backend
*/
g_free (backend->font_name);
g_object_get (settings, "font-name", &backend->font_name, NULL);
return backend->font_name;
}
gint32
_clutter_backend_get_units_serial (ClutterBackend *backend)
{
@ -1262,61 +1094,6 @@ clutter_wayland_set_compositor_display (void *display)
}
#endif
/**
* clutter_set_windowing_backend:
* @backend_type: a comma separated list of windowing backends
*
* Restricts Clutter to only use the specified backend or list of backends.
*
* You can use one of the `CLUTTER_WINDOWING_*` symbols, e.g.
*
* |[<!-- language="C" -->
* clutter_set_windowing_backend (CLUTTER_WINDOWING_X11);
* ]|
*
* Will force Clutter to use the X11 windowing and input backend, and terminate
* if the X11 backend could not be initialized successfully.
*
* Since Clutter 1.26, you can also use a comma-separated list of windowing
* system backends to provide a fallback in case backends are not available or
* enabled, e.g.:
*
* |[<!-- language="C" -->
* clutter_set_windowing_backend ("gdk,wayland,x11");
* ]|
*
* Will make Clutter test for the GDK, Wayland, and X11 backends in that order.
*
* You can use the `*` special value to ask Clutter to use the internally
* defined list of backends. For instance:
*
* |[<!-- language="C" -->
* clutter_set_windowing_backend ("x11,wayland,*");
* ]|
*
* Will make Clutter test the X11 and Wayland backends, and then fall back
* to the internal list of available backends.
*
* This function must be called before the first API call to Clutter, including
* clutter_get_option_context()
*
* Since: 1.16
*/
void
clutter_set_windowing_backend (const char *backend_type)
{
g_return_if_fail (backend_type != NULL);
allowed_backends = g_strdup (backend_type);
}
void
clutter_try_set_windowing_backend (const char *backend_type)
{
if (allowed_backends == NULL)
clutter_set_windowing_backend (backend_type);
}
PangoDirection
_clutter_backend_get_keymap_direction (ClutterBackend *backend)
{
@ -1399,3 +1176,17 @@ clutter_backend_set_input_method (ClutterBackend *backend,
{
g_set_object (&backend->input_method, method);
}
/**
* clutter_backend_get_keymap:
* @backend: the #ClutterBackend
*
* Gets the keymap used by Clutter
*
* Returns: (transfer none): the keymap
**/
ClutterKeymap *
clutter_backend_get_keymap (ClutterBackend *backend)
{
return CLUTTER_BACKEND_GET_CLASS (backend)->get_keymap (backend);
}

View File

@ -34,6 +34,7 @@
#include <cogl/cogl.h>
#include <clutter/clutter-config.h>
#include <clutter/clutter-keymap.h>
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
@ -59,9 +60,6 @@ GType clutter_backend_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterBackend * clutter_get_default_backend (void);
CLUTTER_EXPORT
void clutter_set_windowing_backend (const char *backend_type);
CLUTTER_EXPORT
gdouble clutter_backend_get_resolution (ClutterBackend *backend);
@ -83,6 +81,9 @@ ClutterInputMethod * clutter_backend_get_input_method (Clutter
CLUTTER_EXPORT
void clutter_backend_set_input_method (ClutterBackend *backend,
ClutterInputMethod *method);
CLUTTER_EXPORT
ClutterKeymap * clutter_backend_get_keymap (ClutterBackend *backend);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_H__ */

View File

@ -1146,29 +1146,60 @@ clutter_rect_inset (ClutterRect *rect,
rect->size.height = 0.f;
}
/**
* clutter_rect_scale:
* @rect: a #ClutterRect
* @s_x: an horizontal scale value
* @s_y: a vertical scale value
*
* Scale the rectangle coordinates and size by @s_x horizontally and
* @s_y vertically.
*/
void
clutter_rect_scale (ClutterRect *rect,
float s_x,
float s_y)
{
g_return_if_fail (rect != NULL);
g_return_if_fail (s_x > 0.f);
g_return_if_fail (s_y > 0.f);
clutter_rect_normalize_internal (rect);
rect->origin.x *= s_x;
rect->origin.y *= s_y;
rect->size.width *= s_x;
rect->size.height *= s_y;
}
/**
* clutter_rect_clamp_to_pixel:
* @rect: a #ClutterRect
*
* Rounds the origin of @rect downwards to the nearest integer, and rounds
* the size of @rect upwards to the nearest integer, so that @rect is
* updated to the smallest rectangle capable of fully containing the
* original, fractional rectangle.
* Rounds the origin of @rect downwards to the nearest integer, and recompute the
* the size using the @rect origin and size rounded upwards to the nearest integer,
* so that @rect is updated to the smallest rectangle capable of fully containing
* the original, fractional rectangle in the coordinates space.
*
* Since: 1.12
*/
void
clutter_rect_clamp_to_pixel (ClutterRect *rect)
{
float x2, y2;
g_return_if_fail (rect != NULL);
clutter_rect_normalize_internal (rect);
x2 = rect->origin.x + rect->size.width;
y2 = rect->origin.y + rect->size.height;
rect->origin.x = floorf (rect->origin.x);
rect->origin.y = floorf (rect->origin.y);
rect->size.width = ceilf (rect->size.width);
rect->size.height = ceilf (rect->size.height);
rect->size.width = ceilf (x2) - rect->origin.x;
rect->size.height = ceilf (y2) - rect->origin.y;
}
/**

View File

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

View File

@ -150,9 +150,9 @@ typedef struct _RequestedSize
gfloat natural_size;
} RequestedSize;
static gint distribute_natural_allocation (gint extra_space,
guint n_requested_sizes,
RequestedSize *sizes);
static float distribute_natural_allocation (float extra_space,
unsigned int n_requested_sizes,
RequestedSize *sizes);
static void count_expand_children (ClutterLayoutManager *layout,
ClutterContainer *container,
gint *visible_children,
@ -624,7 +624,19 @@ get_preferred_size_for_opposite_orientation (ClutterBoxLayout *self,
else
{
/* Bring children up to size first */
size = distribute_natural_allocation (MAX (0, size), nvis_children, sizes);
if (isnormal (size) || size == 0)
{
size = distribute_natural_allocation (MAX (0, size),
nvis_children,
sizes);
}
else
{
g_critical ("Actor %s (%p) received the invalid "
"value %f as minimum/natural size\n",
G_OBJECT_TYPE_NAME (container), container, size);
size = 0;
}
/* Calculate space which hasn't distributed yet,
* and is available for expanding children.
@ -879,17 +891,18 @@ compare_gap (gconstpointer p1,
*
* Pulled from gtksizerequest.c from Gtk+
*/
static gint
distribute_natural_allocation (gint extra_space,
guint n_requested_sizes,
static float
distribute_natural_allocation (float extra_space,
unsigned int n_requested_sizes,
RequestedSize *sizes)
{
guint *spreading;
gint i;
unsigned int *spreading;
int i;
g_return_val_if_fail (isnormal (extra_space) || extra_space == 0, 0);
g_return_val_if_fail (extra_space >= 0, 0);
spreading = g_newa (guint, n_requested_sizes);
spreading = g_newa (unsigned int, n_requested_sizes);
for (i = 0; i < n_requested_sizes; i++)
spreading[i] = i;
@ -913,7 +926,7 @@ distribute_natural_allocation (gint extra_space,
/* Sort descending by gap and position. */
g_qsort_with_data (spreading,
n_requested_sizes, sizeof (guint),
n_requested_sizes, sizeof (unsigned int),
compare_gap, sizes);
/* Distribute available space.
@ -925,11 +938,11 @@ distribute_natural_allocation (gint extra_space,
* Sort order and reducing remaining space by assigned space
* ensures that space is distributed equally.
*/
gint glue = (extra_space + i) / (i + 1);
gint gap = sizes[(spreading[i])].natural_size
- sizes[(spreading[i])].minimum_size;
int glue = (extra_space + i) / (i + 1);
int gap = sizes[(spreading[i])].natural_size
- sizes[(spreading[i])].minimum_size;
gint extra = MIN (glue, gap);
int extra = MIN (glue, gap);
sizes[spreading[i]].minimum_size += extra;
@ -1056,7 +1069,9 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
else
{
/* Bring children up to size first */
size = distribute_natural_allocation (MAX (0, size), nvis_children, sizes);
size = (gint) distribute_natural_allocation (MAX (0, (float) size),
nvis_children,
sizes);
/* Calculate space which hasn't distributed yet,
* and is available for expanding children.

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,8 @@
G_BEGIN_DECLS
typedef enum {
typedef enum
{
CLUTTER_DEBUG_MISC = 1 << 0,
CLUTTER_DEBUG_ACTOR = 1 << 1,
CLUTTER_DEBUG_TEXTURE = 1 << 2,
@ -26,12 +27,14 @@ typedef enum {
CLUTTER_DEBUG_OOB_TRANSFORMS = 1 << 16
} ClutterDebugFlag;
typedef enum {
typedef enum
{
CLUTTER_DEBUG_NOP_PICKING = 1 << 0,
CLUTTER_DEBUG_DUMP_PICK_BUFFERS = 1 << 1
} ClutterPickDebugFlag;
typedef enum {
typedef enum
{
CLUTTER_DEBUG_DISABLE_SWAP_EVENTS = 1 << 0,
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS = 1 << 1,
CLUTTER_DEBUG_REDRAWS = 1 << 2,
@ -80,9 +83,9 @@ extern guint clutter_pick_debug_flags;
extern guint clutter_paint_debug_flags;
void _clutter_debug_messagev (const char *format,
va_list var_args);
va_list var_args) G_GNUC_PRINTF (1, 0);
void _clutter_debug_message (const char *format,
...);
...) G_GNUC_PRINTF (1, 2);
G_END_DECLS

View File

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

View File

@ -51,7 +51,8 @@ G_BEGIN_DECLS
*
* Deprecated: 1.22: Use the normalized #ClutterActor pivot point instead
*/
typedef enum { /*< prefix=CLUTTER_GRAVITY >*/
typedef enum /*< prefix=CLUTTER_GRAVITY >*/
{
CLUTTER_GRAVITY_NONE = 0,
CLUTTER_GRAVITY_NORTH,
CLUTTER_GRAVITY_NORTH_EAST,
@ -74,7 +75,8 @@ typedef enum { /*< prefix=CLUTTER_GRAVITY >*/
*
* Since: 0.4
*/
typedef enum { /*< prefix=CLUTTER >*/
typedef enum /*< prefix=CLUTTER >*/
{
CLUTTER_X_AXIS,
CLUTTER_Y_AXIS,
CLUTTER_Z_AXIS
@ -91,7 +93,8 @@ typedef enum { /*< prefix=CLUTTER >*/
*
* Deprecated: 1.22
*/
typedef enum { /*< prefix=CLUTTER_ROTATE >*/
typedef enum /*< prefix=CLUTTER_ROTATE >*/
{
CLUTTER_ROTATE_CW,
CLUTTER_ROTATE_CCW
} ClutterRotateDirection;
@ -107,7 +110,8 @@ typedef enum { /*< prefix=CLUTTER_ROTATE >*/
*
* Since: 0.8
*/
typedef enum { /*< prefix=CLUTTER_REQUEST >*/
typedef enum /*< prefix=CLUTTER_REQUEST >*/
{
CLUTTER_REQUEST_HEIGHT_FOR_WIDTH,
CLUTTER_REQUEST_WIDTH_FOR_HEIGHT,
CLUTTER_REQUEST_CONTENT_SIZE
@ -200,7 +204,8 @@ typedef enum { /*< prefix=CLUTTER_REQUEST >*/
*
* Since: 1.0
*/
typedef enum {
typedef enum
{
CLUTTER_CUSTOM_MODE = 0,
/* linear */
@ -284,7 +289,8 @@ typedef enum {
*
* Deprecated: 1.22: Use #cairo_font_options_t instead
*/
typedef enum { /*< prefix=CLUTTER_FONT >*/
typedef enum /*< prefix=CLUTTER_FONT >*/
{
CLUTTER_FONT_MIPMAPPING = (1 << 0),
CLUTTER_FONT_HINTING = (1 << 1)
} ClutterFontFlags;
@ -300,7 +306,8 @@ typedef enum { /*< prefix=CLUTTER_FONT >*/
*
* Since: 1.2
*/
typedef enum {
typedef enum
{
CLUTTER_TEXT_DIRECTION_DEFAULT,
CLUTTER_TEXT_DIRECTION_LTR,
CLUTTER_TEXT_DIRECTION_RTL
@ -315,7 +322,8 @@ typedef enum {
*
* Since: 1.4
*/
typedef enum {
typedef enum
{
CLUTTER_VERTEX_SHADER,
CLUTTER_FRAGMENT_SHADER
} ClutterShaderType;
@ -350,7 +358,8 @@ typedef enum {
*
* Since: 0.4
*/
typedef enum {
typedef enum
{
CLUTTER_SHIFT_MASK = 1 << 0,
CLUTTER_LOCK_MASK = 1 << 1,
CLUTTER_CONTROL_MASK = 1 << 2,
@ -416,7 +425,8 @@ typedef enum {
* Keyboard accessibility features applied to a ClutterInputDevice keyboard.
*
*/
typedef enum {
typedef enum
{
CLUTTER_A11Y_KEYBOARD_ENABLED = 1 << 0,
CLUTTER_A11Y_TIMEOUT_ENABLED = 1 << 1,
CLUTTER_A11Y_MOUSE_KEYS_ENABLED = 1 << 2,
@ -448,7 +458,8 @@ typedef enum {
*
* Flags used to signal the state of an actor.
*/
typedef enum { /*< prefix=CLUTTER_ACTOR >*/
typedef enum /*< prefix=CLUTTER_ACTOR >*/
{
CLUTTER_ACTOR_MAPPED = 1 << 1,
CLUTTER_ACTOR_REALIZED = 1 << 2,
CLUTTER_ACTOR_REACTIVE = 1 << 3,
@ -468,7 +479,8 @@ typedef enum { /*< prefix=CLUTTER_ACTOR >*/
*
* Since: 1.8
*/
typedef enum { /*< prefix=CLUTTER_OFFSCREEN_REDIRECT >*/
typedef enum /*< prefix=CLUTTER_OFFSCREEN_REDIRECT >*/
{
CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY = 1<<0,
CLUTTER_OFFSCREEN_REDIRECT_ALWAYS = 1<<1
} ClutterOffscreenRedirect;
@ -492,7 +504,8 @@ typedef enum { /*< prefix=CLUTTER_OFFSCREEN_REDIRECT >*/
*
* Since: 1.0
*/
typedef enum {
typedef enum
{
CLUTTER_ALLOCATION_NONE = 0,
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1,
CLUTTER_DELEGATE_LAYOUT = 1 << 2
@ -509,7 +522,8 @@ typedef enum {
*
* Since: 1.4
*/
typedef enum { /*< prefix=CLUTTER_ALIGN >*/
typedef enum /*< prefix=CLUTTER_ALIGN >*/
{
CLUTTER_ALIGN_X_AXIS,
CLUTTER_ALIGN_Y_AXIS,
CLUTTER_ALIGN_BOTH
@ -526,7 +540,8 @@ typedef enum { /*< prefix=CLUTTER_ALIGN >*/
*
* Deprecated: 1.22
*/
typedef enum {
typedef enum
{
CLUTTER_INTERPOLATION_LINEAR,
CLUTTER_INTERPOLATION_CUBIC
} ClutterInterpolation;
@ -551,7 +566,8 @@ typedef enum {
* Deprecated: 1.12: Use #ClutterActorAlign and the #ClutterActor
* API instead
*/
typedef enum {
typedef enum
{
CLUTTER_BIN_ALIGNMENT_FIXED,
CLUTTER_BIN_ALIGNMENT_FILL,
CLUTTER_BIN_ALIGNMENT_START,
@ -576,7 +592,8 @@ typedef enum {
*
* Since: 1.4
*/
typedef enum { /*< prefix=CLUTTER_BIND >*/
typedef enum /*< prefix=CLUTTER_BIND >*/
{
CLUTTER_BIND_X,
CLUTTER_BIND_Y,
CLUTTER_BIND_WIDTH,
@ -595,7 +612,8 @@ typedef enum { /*< prefix=CLUTTER_BIND >*/
*
* Flags passed to the paint or pick method of #ClutterEffect.
*/
typedef enum { /*< prefix=CLUTTER_EFFECT_PAINT >*/
typedef enum /*< prefix=CLUTTER_EFFECT_PAINT >*/
{
CLUTTER_EFFECT_PAINT_ACTOR_DIRTY = (1 << 0)
} ClutterEffectPaintFlags;
@ -611,7 +629,8 @@ typedef enum { /*< prefix=CLUTTER_EFFECT_PAINT >*/
*
* Since: 1.2
*/
typedef enum {
typedef enum
{
CLUTTER_BOX_ALIGNMENT_START,
CLUTTER_BOX_ALIGNMENT_END,
CLUTTER_BOX_ALIGNMENT_CENTER
@ -628,7 +647,8 @@ typedef enum {
*
* Since: 1.8
*/
typedef enum { /*< prefix=CLUTTER_LONG_PRESS >*/
typedef enum /*< prefix=CLUTTER_LONG_PRESS >*/
{
CLUTTER_LONG_PRESS_QUERY,
CLUTTER_LONG_PRESS_ACTIVATE,
CLUTTER_LONG_PRESS_CANCEL
@ -686,7 +706,8 @@ typedef enum { /*< prefix=CLUTTER_LONG_PRESS >*/
*
* Since: 1.6
*/
typedef enum { /*< prefix=CLUTTER_COLOR >*/
typedef enum /*< prefix=CLUTTER_COLOR >*/
{
/* CGA/EGA-like palette */
CLUTTER_COLOR_WHITE = 0,
CLUTTER_COLOR_BLACK,
@ -750,7 +771,8 @@ typedef enum { /*< prefix=CLUTTER_COLOR >*/
*
* Since: 1.4
*/
typedef enum { /*< prefix=CLUTTER_DRAG >*/
typedef enum /*< prefix=CLUTTER_DRAG >*/
{
CLUTTER_DRAG_AXIS_NONE = 0,
CLUTTER_DRAG_X_AXIS,
@ -767,7 +789,8 @@ typedef enum { /*< prefix=CLUTTER_DRAG >*/
*
* Since: 0.6
*/
typedef enum { /*< flags prefix=CLUTTER_EVENT >*/
typedef enum /*< flags prefix=CLUTTER_EVENT >*/
{
CLUTTER_EVENT_NONE = 0,
CLUTTER_EVENT_FLAG_SYNTHETIC = 1 << 0,
CLUTTER_EVENT_FLAG_INPUT_METHOD = 1 << 1,
@ -812,7 +835,8 @@ typedef enum { /*< flags prefix=CLUTTER_EVENT >*/
*
* Since: 0.4
*/
typedef enum { /*< prefix=CLUTTER >*/
typedef enum /*< prefix=CLUTTER >*/
{
CLUTTER_NOTHING = 0,
CLUTTER_KEY_PRESS,
CLUTTER_KEY_RELEASE,
@ -857,7 +881,8 @@ typedef enum { /*< prefix=CLUTTER >*/
*
* Since: 0.4
*/
typedef enum { /*< prefix=CLUTTER_SCROLL >*/
typedef enum /*< prefix=CLUTTER_SCROLL >*/
{
CLUTTER_SCROLL_UP,
CLUTTER_SCROLL_DOWN,
CLUTTER_SCROLL_LEFT,
@ -875,7 +900,8 @@ typedef enum { /*< prefix=CLUTTER_SCROLL >*/
*
* Since: 0.4
*/
typedef enum {
typedef enum
{
CLUTTER_STAGE_STATE_FULLSCREEN = (1 << 1),
CLUTTER_STAGE_STATE_OFFSCREEN = (1 << 2),
CLUTTER_STAGE_STATE_ACTIVATED = (1 << 3)
@ -927,7 +953,8 @@ typedef enum
*
* Since: 1.2
*/
typedef enum { /*< prefix=CLUTTER_FLOW >*/
typedef enum /*< prefix=CLUTTER_FLOW >*/
{
CLUTTER_FLOW_HORIZONTAL,
CLUTTER_FLOW_VERTICAL
} ClutterFlowOrientation;
@ -954,7 +981,8 @@ typedef enum { /*< prefix=CLUTTER_FLOW >*/
*
* Since: 1.0
*/
typedef enum {
typedef enum
{
CLUTTER_POINTER_DEVICE,
CLUTTER_KEYBOARD_DEVICE,
CLUTTER_EXTENSION_DEVICE,
@ -982,7 +1010,8 @@ typedef enum {
*
* Since: 1.6
*/
typedef enum {
typedef enum
{
CLUTTER_INPUT_MODE_MASTER,
CLUTTER_INPUT_MODE_SLAVE,
CLUTTER_INPUT_MODE_FLOATING
@ -1007,7 +1036,8 @@ typedef enum {
*
* Since: 1.6
*/
typedef enum {
typedef enum
{
CLUTTER_INPUT_AXIS_IGNORE,
CLUTTER_INPUT_AXIS_X,
@ -1034,7 +1064,8 @@ typedef enum {
*
* Since: 1.6
*/
typedef enum {
typedef enum
{
CLUTTER_SNAP_EDGE_TOP,
CLUTTER_SNAP_EDGE_RIGHT,
CLUTTER_SNAP_EDGE_BOTTOM,
@ -1051,7 +1082,8 @@ typedef enum {
*
* Since: 1.0
*/
typedef enum {
typedef enum
{
CLUTTER_PICK_NONE = 0,
CLUTTER_PICK_REACTIVE,
CLUTTER_PICK_ALL
@ -1068,7 +1100,8 @@ typedef enum {
*
* Since: 1.8
*/
typedef enum { /*< prefix=CLUTTER_SWIPE_DIRECTION >*/
typedef enum /*< prefix=CLUTTER_SWIPE_DIRECTION >*/
{
CLUTTER_SWIPE_DIRECTION_UP = 1 << 0,
CLUTTER_SWIPE_DIRECTION_DOWN = 1 << 1,
CLUTTER_SWIPE_DIRECTION_LEFT = 1 << 2,
@ -1088,7 +1121,8 @@ typedef enum { /*< prefix=CLUTTER_SWIPE_DIRECTION >*/
*
* Since: 1.12
*/
typedef enum { /*< prefix=CLUTTER_PAN >*/
typedef enum /*< prefix=CLUTTER_PAN >*/
{
CLUTTER_PAN_AXIS_NONE = 0,
CLUTTER_PAN_X_AXIS,
@ -1113,7 +1147,8 @@ typedef enum { /*< prefix=CLUTTER_PAN >*/
*
* Deprecated: 1.22: Use the alignment properties of #ClutterActor
*/
typedef enum {
typedef enum
{
CLUTTER_TABLE_ALIGNMENT_START,
CLUTTER_TABLE_ALIGNMENT_CENTER,
CLUTTER_TABLE_ALIGNMENT_END
@ -1134,7 +1169,8 @@ typedef enum {
* Deprecated: 1.22: The #ClutterTexture class was the only user of
* this API
*/
typedef enum { /*< prefix=CLUTTER_TEXTURE >*/
typedef enum /*< prefix=CLUTTER_TEXTURE >*/
{
CLUTTER_TEXTURE_NONE = 0,
CLUTTER_TEXTURE_RGB_FLAG_BGR = 1 << 1,
CLUTTER_TEXTURE_RGB_FLAG_PREMULT = 1 << 2, /* FIXME: not handled */
@ -1158,7 +1194,8 @@ typedef enum { /*< prefix=CLUTTER_TEXTURE >*/
* this API; use #ClutterImage and clutter_actor_set_content_scaling_filters()
* instead.
*/
typedef enum { /*< prefix=CLUTTER_TEXTURE_QUALITY >*/
typedef enum /*< prefix=CLUTTER_TEXTURE_QUALITY >*/
{
CLUTTER_TEXTURE_QUALITY_LOW,
CLUTTER_TEXTURE_QUALITY_MEDIUM,
CLUTTER_TEXTURE_QUALITY_HIGH
@ -1173,7 +1210,8 @@ typedef enum { /*< prefix=CLUTTER_TEXTURE_QUALITY >*/
*
* Since: 0.6
*/
typedef enum {
typedef enum
{
CLUTTER_TIMELINE_FORWARD,
CLUTTER_TIMELINE_BACKWARD
} ClutterTimelineDirection;
@ -1192,7 +1230,8 @@ typedef enum {
*
* Since: 1.0
*/
typedef enum { /*< prefix=CLUTTER_UNIT >*/
typedef enum /*< prefix=CLUTTER_UNIT >*/
{
CLUTTER_UNIT_PIXEL,
CLUTTER_UNIT_EM,
CLUTTER_UNIT_MM,
@ -1222,7 +1261,8 @@ typedef enum { /*< prefix=CLUTTER_UNIT >*/
*
* Since: 1.0
*/
typedef enum {
typedef enum
{
CLUTTER_PATH_MOVE_TO = 0,
CLUTTER_PATH_LINE_TO = 1,
CLUTTER_PATH_CURVE_TO = 2,
@ -1253,7 +1293,8 @@ typedef enum {
*
* Since: 1.10
*/
typedef enum {
typedef enum
{
CLUTTER_ACTOR_ALIGN_FILL,
CLUTTER_ACTOR_ALIGN_START,
CLUTTER_ACTOR_ALIGN_CENTER,
@ -1273,7 +1314,8 @@ typedef enum {
*
* Since: 1.10
*/
typedef enum {
typedef enum
{
CLUTTER_REPAINT_FLAGS_PRE_PAINT = 1 << 0,
CLUTTER_REPAINT_FLAGS_POST_PAINT = 1 << 1,
CLUTTER_REPAINT_FLAGS_QUEUE_REDRAW_ON_ADD = 1 << 2
@ -1298,7 +1340,8 @@ typedef enum {
*
* Since: 1.10
*/
typedef enum {
typedef enum
{
CLUTTER_CONTENT_GRAVITY_TOP_LEFT,
CLUTTER_CONTENT_GRAVITY_TOP,
CLUTTER_CONTENT_GRAVITY_TOP_RIGHT,
@ -1328,7 +1371,8 @@ typedef enum {
*
* Since: 1.10
*/
typedef enum {
typedef enum
{
CLUTTER_SCALING_FILTER_LINEAR,
CLUTTER_SCALING_FILTER_NEAREST,
CLUTTER_SCALING_FILTER_TRILINEAR
@ -1343,7 +1387,8 @@ typedef enum {
*
* Since: 1.12
*/
typedef enum {
typedef enum
{
CLUTTER_ORIENTATION_HORIZONTAL,
CLUTTER_ORIENTATION_VERTICAL
} ClutterOrientation;
@ -1359,7 +1404,8 @@ typedef enum {
*
* Since: 1.12
*/
typedef enum { /*< prefix=CLUTTER_SCROLL >*/
typedef enum /*< prefix=CLUTTER_SCROLL >*/
{
CLUTTER_SCROLL_NONE = 0,
CLUTTER_SCROLL_HORIZONTALLY = 1 << 0,
@ -1379,7 +1425,8 @@ typedef enum { /*< prefix=CLUTTER_SCROLL >*/
*
* Since: 1.12
*/
typedef enum {
typedef enum
{
CLUTTER_GRID_POSITION_LEFT,
CLUTTER_GRID_POSITION_RIGHT,
CLUTTER_GRID_POSITION_TOP,
@ -1397,7 +1444,8 @@ typedef enum {
*
* Since: 1.12
*/
typedef enum {
typedef enum
{
CLUTTER_REPEAT_NONE = 0,
CLUTTER_REPEAT_X_AXIS = 1 << 0,
CLUTTER_REPEAT_Y_AXIS = 1 << 1,
@ -1419,7 +1467,8 @@ typedef enum {
*
* Since: 1.12
*/
typedef enum {
typedef enum
{
CLUTTER_STEP_MODE_START,
CLUTTER_STEP_MODE_END
} ClutterStepMode;
@ -1435,7 +1484,8 @@ typedef enum {
*
* Since: 1.12
*/
typedef enum { /*< prefix=CLUTTER_ZOOM >*/
typedef enum /*< prefix=CLUTTER_ZOOM >*/
{
CLUTTER_ZOOM_X_AXIS,
CLUTTER_ZOOM_Y_AXIS,
CLUTTER_ZOOM_BOTH
@ -1458,7 +1508,8 @@ typedef enum { /*< prefix=CLUTTER_ZOOM >*/
*
* Since: 1.18
*/
typedef enum {
typedef enum
{
CLUTTER_GESTURE_TRIGGER_EDGE_NONE = 0,
CLUTTER_GESTURE_TRIGGER_EDGE_AFTER,
CLUTTER_GESTURE_TRIGGER_EDGE_BEFORE
@ -1494,7 +1545,8 @@ typedef enum {
*
* Since: 1.24
*/
typedef enum {
typedef enum
{
CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN,
CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE,
CLUTTER_TOUCHPAD_GESTURE_PHASE_END,
@ -1516,7 +1568,8 @@ typedef enum {
*
* Since: 1.26
*/
typedef enum {
typedef enum
{
CLUTTER_SCROLL_SOURCE_UNKNOWN,
CLUTTER_SCROLL_SOURCE_WHEEL,
CLUTTER_SCROLL_SOURCE_FINGER,
@ -1534,7 +1587,8 @@ typedef enum {
*
* Since: 1.26
*/
typedef enum {
typedef enum
{
CLUTTER_SCROLL_FINISHED_NONE = 0,
CLUTTER_SCROLL_FINISHED_HORIZONTAL = 1 << 0,
CLUTTER_SCROLL_FINISHED_VERTICAL = 1 << 1
@ -1555,7 +1609,8 @@ typedef enum {
*
* Since: 1.28
*/
typedef enum {
typedef enum
{
CLUTTER_INPUT_DEVICE_TOOL_NONE,
CLUTTER_INPUT_DEVICE_TOOL_PEN,
CLUTTER_INPUT_DEVICE_TOOL_ERASER,
@ -1566,17 +1621,20 @@ typedef enum {
CLUTTER_INPUT_DEVICE_TOOL_LENS
} ClutterInputDeviceToolType;
typedef enum {
typedef enum
{
CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN,
CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER,
} ClutterInputDevicePadSource;
typedef enum {
typedef enum
{
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE,
} ClutterInputDeviceMapping;
typedef enum {
typedef enum
{
CLUTTER_INPUT_CONTENT_HINT_COMPLETION = 1 << 0,
CLUTTER_INPUT_CONTENT_HINT_SPELLCHECK = 1 << 1,
CLUTTER_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION = 1 << 2,
@ -1589,7 +1647,8 @@ typedef enum {
CLUTTER_INPUT_CONTENT_HINT_MULTILINE = 1 << 9,
} ClutterInputContentHintFlags;
typedef enum {
typedef enum
{
CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL,
CLUTTER_INPUT_CONTENT_PURPOSE_ALPHA,
CLUTTER_INPUT_CONTENT_PURPOSE_DIGITS,
@ -1605,7 +1664,8 @@ typedef enum {
CLUTTER_INPUT_CONTENT_PURPOSE_TERMINAL,
} ClutterInputContentPurpose;
typedef enum {
typedef enum
{
CLUTTER_INPUT_PANEL_STATE_OFF,
CLUTTER_INPUT_PANEL_STATE_ON,
CLUTTER_INPUT_PANEL_STATE_TOGGLE,

View File

@ -14,7 +14,8 @@ G_BEGIN_DECLS
typedef struct _ClutterEventTranslator ClutterEventTranslator;
typedef struct _ClutterEventTranslatorIface ClutterEventTranslatorIface;
typedef enum {
typedef enum
{
CLUTTER_TRANSLATE_CONTINUE,
CLUTTER_TRANSLATE_REMOVE,
CLUTTER_TRANSLATE_QUEUE

View File

@ -772,7 +772,10 @@ void clutter_event_get_gesture_motion_delta (const Clut
gdouble *dx,
gdouble *dy);
CLUTTER_EXPORT
ClutterScrollSource clutter_event_get_scroll_source (const ClutterEvent *event);
CLUTTER_EXPORT
ClutterScrollFinishFlags clutter_event_get_scroll_finish_flags (const ClutterEvent *event);
CLUTTER_EXPORT

View File

@ -53,9 +53,11 @@
struct _ClutterImagePrivate
{
CoglTexture *texture;
gint width;
gint height;
};
static void clutter_content_iface_init (ClutterContentIface *iface);
static void clutter_content_iface_init (ClutterContentInterface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterImage, clutter_image, G_TYPE_OBJECT,
G_ADD_PRIVATE (ClutterImage)
@ -68,6 +70,27 @@ clutter_image_error_quark (void)
return g_quark_from_static_string ("clutter-image-error-quark");
}
static void
update_image_size (ClutterImage *self)
{
gint width, height;
if (self->priv->texture == NULL)
return;
width = cogl_texture_get_width (self->priv->texture);
height = cogl_texture_get_height (self->priv->texture);
if (self->priv->width == width &&
self->priv->height == height)
return;
self->priv->width = width;
self->priv->height = height;
clutter_content_invalidate_size (CLUTTER_CONTENT (self));
}
static void
clutter_image_finalize (GObject *gobject)
{
@ -131,7 +154,7 @@ clutter_image_get_preferred_size (ClutterContent *content,
}
static void
clutter_content_iface_init (ClutterContentIface *iface)
clutter_content_iface_init (ClutterContentInterface *iface)
{
iface->get_preferred_size = clutter_image_get_preferred_size;
iface->paint_content = clutter_image_paint_content;
@ -238,6 +261,7 @@ clutter_image_set_data (ClutterImage *image,
}
clutter_content_invalidate (CLUTTER_CONTENT (image));
update_image_size (image);
return TRUE;
}
@ -306,6 +330,7 @@ clutter_image_set_bytes (ClutterImage *image,
}
clutter_content_invalidate (CLUTTER_CONTENT (image));
update_image_size (image);
return TRUE;
}
@ -399,6 +424,7 @@ clutter_image_set_area (ClutterImage *image,
}
clutter_content_invalidate (CLUTTER_CONTENT (image));
update_image_size (image);
return TRUE;
}

View File

@ -63,7 +63,8 @@ typedef struct _ClutterImageClass ClutterImageClass;
*
* Since: 1.10
*/
typedef enum {
typedef enum
{
CLUTTER_IMAGE_ERROR_INVALID_DATA
} ClutterImageError;

View File

@ -35,7 +35,8 @@ struct _ClutterInputDeviceToolPrivate
guint64 id;
};
enum {
enum
{
PROP_0,
PROP_TYPE,
PROP_SERIAL,

View File

@ -175,7 +175,8 @@ clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
}
void
clutter_input_focus_request_toggle_input_panel (ClutterInputFocus *focus)
clutter_input_focus_set_input_panel_state (ClutterInputFocus *focus,
ClutterInputPanelState state)
{
ClutterInputFocusPrivate *priv;
@ -184,7 +185,7 @@ clutter_input_focus_request_toggle_input_panel (ClutterInputFocus *focus)
priv = clutter_input_focus_get_instance_private (focus);
clutter_input_method_toggle_input_panel (priv->im);
clutter_input_method_set_input_panel_state (priv->im, state);
}
void

View File

@ -78,6 +78,7 @@ CLUTTER_EXPORT
void clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
gboolean can_show_preedit);
CLUTTER_EXPORT
void clutter_input_focus_request_toggle_input_panel (ClutterInputFocus *focus);
void clutter_input_focus_set_input_panel_state (ClutterInputFocus *focus,
ClutterInputPanelState state);
#endif /* __CLUTTER_INPUT_FOCUS_H__ */

View File

@ -37,7 +37,8 @@ struct _ClutterInputMethodPrivate
gboolean can_show_preedit;
};
enum {
enum
{
COMMIT,
DELETE_SURROUNDING,
REQUEST_SURROUNDING,
@ -46,7 +47,8 @@ enum {
N_SIGNALS,
};
enum {
enum
{
PROP_0,
PROP_CONTENT_HINTS,
PROP_CONTENT_PURPOSE,
@ -264,9 +266,6 @@ clutter_input_method_focus_out (ClutterInputMethod *im)
klass = CLUTTER_INPUT_METHOD_GET_CLASS (im);
klass->focus_out (im);
g_signal_emit (im, signals[INPUT_PANEL_STATE],
0, CLUTTER_INPUT_PANEL_STATE_OFF);
}
ClutterInputFocus *
@ -361,12 +360,12 @@ clutter_input_method_notify_key_event (ClutterInputMethod *im,
}
void
clutter_input_method_toggle_input_panel (ClutterInputMethod *im)
clutter_input_method_set_input_panel_state (ClutterInputMethod *im,
ClutterInputPanelState state)
{
g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
g_signal_emit (im, signals[INPUT_PANEL_STATE], 0,
CLUTTER_INPUT_PANEL_STATE_TOGGLE);
g_signal_emit (im, signals[INPUT_PANEL_STATE], 0, state);
}
void

View File

@ -83,7 +83,8 @@ void clutter_input_method_notify_key_event (ClutterInputMethod *im,
const ClutterEvent *event,
gboolean filtered);
CLUTTER_EXPORT
void clutter_input_method_request_toggle_input_panel (ClutterInputMethod *im);
void clutter_input_method_set_input_panel_state (ClutterInputMethod *im,
ClutterInputPanelState state);
CLUTTER_EXPORT
void clutter_input_method_forward_key (ClutterInputMethod *im,

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2018 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "clutter-build-config.h"
#include "clutter-keymap.h"
#include "clutter-private.h"
G_DEFINE_ABSTRACT_TYPE (ClutterKeymap, clutter_keymap, G_TYPE_OBJECT)
enum
{
STATE_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS] = { 0, };
static void
clutter_keymap_class_init (ClutterKeymapClass *klass)
{
signals[STATE_CHANGED] =
g_signal_new (I_("state-changed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
clutter_keymap_init (ClutterKeymap *keymap)
{
}
gboolean
clutter_keymap_get_num_lock_state (ClutterKeymap *keymap)
{
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_num_lock_state (keymap);
}
gboolean
clutter_keymap_get_caps_lock_state (ClutterKeymap *keymap)
{
return CLUTTER_KEYMAP_GET_CLASS (keymap)->get_caps_lock_state (keymap);
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef CLUTTER_KEYMAP_H
#define CLUTTER_KEYMAP_H
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <clutter/clutter-macros.h>
#include <glib-object.h>
typedef struct _ClutterKeymap ClutterKeymap;
typedef struct _ClutterKeymapClass ClutterKeymapClass;
struct _ClutterKeymapClass
{
GObjectClass parent_class;
gboolean (* get_num_lock_state) (ClutterKeymap *keymap);
gboolean (* get_caps_lock_state) (ClutterKeymap *keymap);
};
#define CLUTTER_TYPE_KEYMAP (clutter_keymap_get_type ())
CLUTTER_EXPORT
G_DECLARE_DERIVABLE_TYPE (ClutterKeymap, clutter_keymap,
CLUTTER, KEYMAP,
GObject)
CLUTTER_EXPORT
gboolean clutter_keymap_get_num_lock_state (ClutterKeymap *keymap);
CLUTTER_EXPORT
gboolean clutter_keymap_get_caps_lock_state (ClutterKeymap *keymap);
#endif /* CLUTTER_KEYMAP_H */

View File

@ -193,17 +193,6 @@ clutter_config_read_from_key_file (GKeyFile *keyfile)
if (!g_key_file_has_group (keyfile, ENVIRONMENT_GROUP))
return;
str_value =
g_key_file_get_string (keyfile, ENVIRONMENT_GROUP,
"Backends",
&key_error);
if (key_error != NULL)
g_clear_error (&key_error);
else
clutter_try_set_windowing_backend (str_value);
g_free (str_value);
str_value =
g_key_file_get_string (keyfile, ENVIRONMENT_GROUP,
"Drivers",

View File

@ -53,7 +53,8 @@ G_BEGIN_DECLS
*
* Since: 0.2
*/
typedef enum {
typedef enum
{
CLUTTER_INIT_SUCCESS = 1,
CLUTTER_INIT_ERROR_UNKNOWN = 0,
CLUTTER_INIT_ERROR_THREADS = -1,

View File

@ -1,6 +1,7 @@
BOOLEAN:BOXED
BOOLEAN:BOXED,INT,INT
BOOLEAN:OBJECT,BOOLEAN
BOOLEAN:OBJECT,BOXED
BOOLEAN:OBJECT,BOXED,DOUBLE
BOOLEAN:OBJECT,DOUBLE
BOOLEAN:OBJECT,ENUM

View File

@ -109,7 +109,8 @@ static GSourceFuncs clock_funcs = {
NULL
};
static void clutter_master_clock_iface_init (ClutterMasterClockIface *iface);
static void
clutter_master_clock_iface_init (ClutterMasterClockInterface *iface);
#define clutter_master_clock_default_get_type _clutter_master_clock_default_get_type
@ -689,7 +690,7 @@ clutter_master_clock_default_set_paused (ClutterMasterClock *clock,
}
static void
clutter_master_clock_iface_init (ClutterMasterClockIface *iface)
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;

View File

@ -37,10 +37,6 @@
#include "clutter-master-clock-default.h"
#include "clutter-private.h"
#define clutter_master_clock_get_type _clutter_master_clock_get_type
typedef ClutterMasterClockIface ClutterMasterClockInterface;
G_DEFINE_INTERFACE (ClutterMasterClock, clutter_master_clock, G_TYPE_OBJECT)
static void

View File

@ -28,15 +28,12 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_MASTER_CLOCK (_clutter_master_clock_get_type ())
#define CLUTTER_MASTER_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK, ClutterMasterClock))
#define CLUTTER_IS_MASTER_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK))
#define CLUTTER_MASTER_CLOCK_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_MASTER_CLOCK, ClutterMasterClockIface))
#define CLUTTER_TYPE_MASTER_CLOCK (clutter_master_clock_get_type ())
G_DECLARE_INTERFACE (ClutterMasterClock, clutter_master_clock,
CLUTTER, MASTER_CLOCK,
GObject)
typedef struct _ClutterMasterClock ClutterMasterClock; /* dummy */
typedef struct _ClutterMasterClockIface ClutterMasterClockIface;
struct _ClutterMasterClockIface
struct _ClutterMasterClockInterface
{
/*< private >*/
GTypeInterface parent_iface;
@ -51,8 +48,6 @@ struct _ClutterMasterClockIface
gboolean paused);
};
GType _clutter_master_clock_get_type (void) G_GNUC_CONST;
ClutterMasterClock * _clutter_master_clock_get_default (void);
void _clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
ClutterTimeline *timeline);

View File

@ -49,6 +49,12 @@ void clutter_stage_freeze_updates (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_thaw_updates (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_stage_update_resource_scales (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_actor_has_damage (ClutterActor *actor);
#undef __CLUTTER_H_INSIDE__
#endif /* __CLUTTER_MUTTER_H__ */

View File

@ -66,12 +66,16 @@
#include "clutter-offscreen-effect.h"
#include <math.h>
#include "cogl/cogl.h"
#include "clutter-actor-private.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-paint-volume-private.h"
#include "clutter-actor-box-private.h"
struct _ClutterOffscreenEffectPrivate
{
@ -82,27 +86,19 @@ struct _ClutterOffscreenEffectPrivate
ClutterActor *actor;
ClutterActor *stage;
gfloat x_offset;
gfloat y_offset;
ClutterVertex position;
int fbo_offset_x;
int fbo_offset_y;
/* This is the calculated size of the fbo before being passed
through create_texture(). This needs to be tracked separately so
that we can detect when a different size is calculated and
regenerate the fbo */
int fbo_width;
int fbo_height;
int target_width;
int target_height;
gint old_opacity_override;
/* The matrix that was current the last time the fbo was updated. We
need to keep track of this to detect when we can reuse the
contents of the fbo without redrawing the actor. We need the
actual matrix rather than just detecting queued redraws on the
actor because any change in the parent hierarchy (even just a
translation) could cause the actor to look completely different
and it won't cause a redraw to be queued on the parent's
children. */
CoglMatrix last_matrix_drawn;
};
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterOffscreenEffect,
@ -141,8 +137,35 @@ clutter_offscreen_effect_real_create_texture (ClutterOffscreenEffect *effect,
COGL_PIXEL_FORMAT_RGBA_8888_PRE);
}
static void
ensure_pipeline_filter_for_scale (ClutterOffscreenEffect *self,
float resource_scale)
{
CoglPipelineFilter filter;
if (!self->priv->target)
return;
/* If no fractional scaling is set, we're always going to render the texture
at a 1:1 texel:pixel ratio so, in such case we can use 'nearest' filtering
to decrease the effects of rounding errors in the geometry calculation;
if instead we we're using a global fractional scaling we need to make sure
that we're using the default linear effect, not to create artifacts when
scaling down the texture */
if (fmodf (resource_scale, 1.0f) == 0)
filter = COGL_PIPELINE_FILTER_NEAREST;
else
filter = COGL_PIPELINE_FILTER_LINEAR;
cogl_pipeline_set_layer_filters (self->priv->target, 0 /* layer_index */,
filter, filter);
}
static gboolean
update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
update_fbo (ClutterEffect *effect,
int target_width,
int target_height,
float resource_scale)
{
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
ClutterOffscreenEffectPrivate *priv = self->priv;
@ -157,10 +180,13 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
return FALSE;
}
if (priv->fbo_width == fbo_width &&
priv->fbo_height == fbo_height &&
if (priv->target_width == target_width &&
priv->target_height == target_height &&
priv->offscreen != NULL)
{
ensure_pipeline_filter_for_scale (self, resource_scale);
return TRUE;
}
if (priv->target == NULL)
{
@ -168,14 +194,7 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
clutter_backend_get_cogl_context (clutter_get_default_backend ());
priv->target = cogl_pipeline_new (ctx);
/* We're always going to render the texture at a 1:1 texel:pixel
ratio so we can use 'nearest' filtering to decrease the
effects of rounding errors in the geometry calculation */
cogl_pipeline_set_layer_filters (priv->target,
0, /* layer_index */
COGL_PIPELINE_FILTER_NEAREST,
COGL_PIPELINE_FILTER_NEAREST);
ensure_pipeline_filter_for_scale (self, resource_scale);
}
if (priv->texture != NULL)
@ -191,14 +210,14 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
}
priv->texture =
clutter_offscreen_effect_create_texture (self, fbo_width, fbo_height);
clutter_offscreen_effect_create_texture (self, target_width, target_height);
if (priv->texture == NULL)
return FALSE;
cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture);
priv->fbo_width = fbo_width;
priv->fbo_height = fbo_height;
priv->target_width = target_width;
priv->target_height = target_height;
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
if (priv->offscreen == NULL)
@ -208,8 +227,8 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
cogl_handle_unref (priv->target);
priv->target = NULL;
priv->fbo_width = 0;
priv->fbo_height = 0;
priv->target_width = 0;
priv->target_height = 0;
return FALSE;
}
@ -222,15 +241,17 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
{
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
ClutterOffscreenEffectPrivate *priv = self->priv;
ClutterActorBox box;
ClutterActorBox raw_box, box;
ClutterActor *stage;
CoglMatrix projection;
CoglMatrix projection, old_modelview, modelview;
const ClutterPaintVolume *volume;
CoglColor transparent;
gfloat stage_width, stage_height;
gfloat fbo_width = -1, fbo_height = -1;
gfloat width, height;
gfloat xexpand, yexpand;
int texture_width, texture_height;
gfloat target_width = -1, target_height = -1;
gfloat resource_scale;
gfloat ceiled_resource_scale;
ClutterVertex local_offset = { 0.f, 0.f, 0.f };
gfloat old_viewport[4];
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)))
return FALSE;
@ -241,92 +262,98 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
stage = _clutter_actor_get_stage_internal (priv->actor);
clutter_actor_get_size (stage, &stage_width, &stage_height);
/* The paint box is the bounding box of the actor's paint volume in
* stage coordinates. This will give us the size for the framebuffer
* we need to redirect its rendering offscreen and its position will
* be used to setup an offset viewport */
if (clutter_actor_get_paint_box (priv->actor, &box))
if (_clutter_actor_get_real_resource_scale (priv->actor, &resource_scale))
{
clutter_actor_box_get_size (&box, &fbo_width, &fbo_height);
clutter_actor_box_get_origin (&box, &priv->x_offset, &priv->y_offset);
fbo_width = MIN (fbo_width, stage_width);
fbo_height = MIN (fbo_height, stage_height);
ceiled_resource_scale = ceilf (resource_scale);
stage_width *= ceiled_resource_scale;
stage_height *= ceiled_resource_scale;
}
else
{
fbo_width = stage_width;
fbo_height = stage_height;
/* We are sure we have a resource scale set to a good value at paint */
g_assert_not_reached ();
}
if (fbo_width == stage_width)
priv->x_offset = 0.0f;
if (fbo_height == stage_height)
priv->y_offset = 0.0f;
/* 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
* priv->actor so we need to be careful to avoid querying the transformation
* of priv->actor (like clutter_actor_get_paint_box would). Just stay in
* local coordinates for now...
*/
volume = clutter_actor_get_paint_volume (priv->actor);
if (volume)
{
ClutterPaintVolume mutable_volume;
_clutter_paint_volume_copy_static (volume, &mutable_volume);
_clutter_paint_volume_get_bounding_box (&mutable_volume, &raw_box);
clutter_paint_volume_free (&mutable_volume);
}
else
{
clutter_actor_get_allocation_box (priv->actor, &raw_box);
}
box = raw_box;
_clutter_actor_box_enlarge_for_effects (&box);
priv->fbo_offset_x = box.x1 - raw_box.x1;
priv->fbo_offset_y = box.y1 - raw_box.y1;
clutter_actor_box_scale (&box, ceiled_resource_scale);
clutter_actor_box_get_size (&box, &target_width, &target_height);
target_width = ceilf (target_width);
target_height = ceilf (target_height);
/* First assert that the framebuffer is the right size... */
if (!update_fbo (effect, fbo_width, fbo_height))
if (!update_fbo (effect, target_width, target_height, resource_scale))
return FALSE;
texture_width = cogl_texture_get_width (priv->texture);
texture_height = cogl_texture_get_height (priv->texture);
/* get the current modelview matrix so that we can copy it to the
* framebuffer. We also store the matrix that was last used when we
* updated the FBO so that we can detect when we don't need to
* update the FBO to paint a second time */
cogl_get_modelview_matrix (&priv->last_matrix_drawn);
cogl_get_modelview_matrix (&old_modelview);
/* let's draw offscreen */
cogl_push_framebuffer (priv->offscreen);
/* Copy the modelview that would have been used if rendering onscreen */
cogl_set_modelview_matrix (&priv->last_matrix_drawn);
/* Set up the viewport so that it has the same size as the stage,
* but offset it so that the actor of interest lands on our
* framebuffer. */
clutter_actor_get_size (priv->stage, &width, &height);
/* Expand the viewport if the actor is partially off-stage,
* otherwise the actor will end up clipped to the stage viewport
/* We don't want the FBO contents to be transformed. That could waste memory
* (e.g. during zoom), or result in something that's not rectangular (clipped
* incorrectly). So drop the modelview matrix of the current paint chain.
* This is fine since paint_texture runs with the same modelview matrix,
* so it will come out correctly whenever that is used to put the FBO
* contents on screen...
*/
xexpand = 0.f;
if (priv->x_offset < 0.f)
xexpand = -priv->x_offset;
if (priv->x_offset + texture_width > width)
xexpand = MAX (xexpand, (priv->x_offset + texture_width) - width);
clutter_actor_get_transform (priv->stage, &modelview);
cogl_set_modelview_matrix (&modelview);
yexpand = 0.f;
if (priv->y_offset < 0.f)
yexpand = -priv->y_offset;
if (priv->y_offset + texture_height > height)
yexpand = MAX (yexpand, (priv->y_offset + texture_height) - height);
/* Save the original viewport for calculating priv->position */
_clutter_stage_get_viewport (CLUTTER_STAGE (priv->stage),
&old_viewport[0],
&old_viewport[1],
&old_viewport[2],
&old_viewport[3]);
/* Set the viewport */
cogl_set_viewport (-(priv->x_offset + xexpand), -(priv->y_offset + yexpand),
width + (2 * xexpand), height + (2 * yexpand));
/* Set up the viewport so that it has the same size as the stage (avoid
* distortion), but translated to account for the FBO offset...
*/
cogl_set_viewport (-priv->fbo_offset_x,
-priv->fbo_offset_y,
stage_width,
stage_height);
/* Copy the stage's projection matrix across to the framebuffer */
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (priv->stage),
&projection);
/* If we've expanded the viewport, make sure to scale the projection
* matrix accordingly (as it's been initialised to work with the
* original viewport and not our expanded one).
/* Now save the global position of the effect (not just of the actor).
* It doesn't appear anyone actually uses this yet, but get_target_rect is
* documented as returning it. So we should...
*/
if (xexpand > 0.f || yexpand > 0.f)
{
gfloat new_width, new_height;
new_width = width + (2 * xexpand);
new_height = height + (2 * yexpand);
cogl_matrix_scale (&projection,
width / new_width,
height / new_height,
1);
}
_clutter_util_fully_transform_vertices (&old_modelview,
&projection,
old_viewport,
&local_offset,
&priv->position,
1);
cogl_set_projection_matrix (&projection);
@ -382,16 +409,26 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect)
{
ClutterOffscreenEffectPrivate *priv = effect->priv;
CoglMatrix modelview;
float resource_scale;
cogl_push_matrix ();
/* Now reset the modelview to put us in stage coordinates so
* we can drawn the result of our offscreen render as a textured
* quad... */
/* The current modelview matrix is *almost* perfect already. It's only
* missing a correction for the expanded FBO and offset rendering within...
*/
cogl_get_modelview_matrix (&modelview);
cogl_matrix_init_identity (&modelview);
_clutter_actor_apply_modelview_transform (priv->stage, &modelview);
cogl_matrix_translate (&modelview, priv->x_offset, priv->y_offset, 0.0f);
if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) &&
resource_scale != 1.0f)
{
float paint_scale = 1.0f / resource_scale;
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
}
cogl_matrix_translate (&modelview,
priv->fbo_offset_x,
priv->fbo_offset_y,
0.0f);
cogl_set_modelview_matrix (&modelview);
/* paint the target material; this is virtualized for
@ -428,16 +465,11 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
{
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
ClutterOffscreenEffectPrivate *priv = self->priv;
CoglMatrix matrix;
cogl_get_modelview_matrix (&matrix);
/* If we've already got a cached image for the same matrix and the
actor hasn't been redrawn then we can just use the cached image
in the fbo */
if (priv->offscreen == NULL ||
(flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY) ||
!cogl_matrix_equal (&matrix, &priv->last_matrix_drawn))
/* If we've already got a cached image and the actor hasn't been redrawn
* then we can just use the cached image in the FBO.
*/
if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY))
{
/* Chain up to the parent paint method which will call the pre and
post paint functions to update the image */
@ -663,8 +695,8 @@ clutter_offscreen_effect_get_target_rect (ClutterOffscreenEffect *effect,
return FALSE;
clutter_rect_init (rect,
priv->x_offset,
priv->y_offset,
priv->position.x,
priv->position.y,
cogl_texture_get_width (priv->texture),
cogl_texture_get_height (priv->texture));

View File

@ -74,9 +74,11 @@ struct _ClutterPaintNodeClass
#define PAINT_OP_INIT { PAINT_OP_INVALID }
typedef enum {
typedef enum
{
PAINT_OP_INVALID = 0,
PAINT_OP_TEX_RECT,
PAINT_OP_MULTITEX_RECT,
PAINT_OP_PATH,
PAINT_OP_PRIMITIVE
} PaintOpCode;
@ -85,6 +87,8 @@ struct _ClutterPaintOperation
{
PaintOpCode opcode;
GArray *multitex_coords;
union {
float texrect[8];
@ -94,7 +98,6 @@ struct _ClutterPaintOperation
} op;
};
GType _clutter_root_node_get_type (void) G_GNUC_CONST;
GType _clutter_transform_node_get_type (void) G_GNUC_CONST;
GType _clutter_dummy_node_get_type (void) G_GNUC_CONST;
@ -107,13 +110,9 @@ void _clutter_paint_operation_paint_primitive (const C
void _clutter_paint_node_init_types (void);
gpointer _clutter_paint_node_create (GType gtype);
ClutterPaintNode * _clutter_root_node_new (CoglFramebuffer *framebuffer,
const ClutterColor *clear_color,
CoglBufferBit clear_flags);
ClutterPaintNode * _clutter_transform_node_new (const CoglMatrix *matrix);
ClutterPaintNode * _clutter_dummy_node_new (ClutterActor *actor);
void _clutter_paint_node_paint (ClutterPaintNode *root);
void _clutter_paint_node_dump_tree (ClutterPaintNode *root);
G_GNUC_INTERNAL

View File

@ -761,6 +761,11 @@ clutter_paint_operation_clear (ClutterPaintOperation *op)
case PAINT_OP_TEX_RECT:
break;
case PAINT_OP_MULTITEX_RECT:
if (op->multitex_coords != NULL)
g_array_unref (op->multitex_coords);
break;
case PAINT_OP_PATH:
if (op->op.path != NULL)
cogl_object_unref (op->op.path);
@ -794,6 +799,27 @@ clutter_paint_op_init_tex_rect (ClutterPaintOperation *op,
op->op.texrect[7] = y_2;
}
static inline void
clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op,
const ClutterActorBox *rect,
const float *tex_coords,
unsigned int tex_coords_len)
{
clutter_paint_operation_clear (op);
op->opcode = PAINT_OP_MULTITEX_RECT;
op->multitex_coords = g_array_sized_new (FALSE, FALSE,
sizeof (float),
tex_coords_len);
g_array_append_vals (op->multitex_coords, tex_coords, tex_coords_len);
op->op.texrect[0] = rect->x1;
op->op.texrect[1] = rect->y1;
op->op.texrect[2] = rect->x2;
op->op.texrect[3] = rect->y2;
}
static inline void
clutter_paint_op_init_path (ClutterPaintOperation *op,
CoglPath *path)
@ -881,6 +907,33 @@ clutter_paint_node_add_texture_rectangle (ClutterPaintNode *node,
g_array_append_val (node->operations, operation);
}
/**
* clutter_paint_node_add_multitexture_rectangle:
* @node: a #ClutterPaintNode
* @rect: a #ClutterActorBox
* @text_coords: array of multitexture values
* @text_coords_len: number of items of @text_coords
*
* Adds a rectangle region to the @node, with multitexture coordinates.
*/
void
clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node,
const ClutterActorBox *rect,
const float *text_coords,
unsigned int text_coords_len)
{
ClutterPaintOperation operation = PAINT_OP_INIT;
g_return_if_fail (CLUTTER_IS_PAINT_NODE (node));
g_return_if_fail (rect != NULL);
clutter_paint_node_maybe_init_operations (node);
clutter_paint_op_init_multitex_rect (&operation, rect, text_coords, text_coords_len);
g_array_append_val (node->operations, operation);
}
/**
* clutter_paint_node_add_path: (skip)
* @node: a #ClutterPaintNode
@ -936,15 +989,15 @@ clutter_paint_node_add_primitive (ClutterPaintNode *node,
g_array_append_val (node->operations, operation);
}
/*< private >
* _clutter_paint_node_paint:
/**
* clutter_paint_node_paint:
* @node: a #ClutterPaintNode
*
* Paints the @node using the class implementation, traversing
* its children, if any.
*/
void
_clutter_paint_node_paint (ClutterPaintNode *node)
clutter_paint_node_paint (ClutterPaintNode *node)
{
ClutterPaintNodeClass *klass = CLUTTER_PAINT_NODE_GET_CLASS (node);
ClutterPaintNode *iter;
@ -961,7 +1014,7 @@ _clutter_paint_node_paint (ClutterPaintNode *node)
iter != NULL;
iter = iter->next_sibling)
{
_clutter_paint_node_paint (iter);
clutter_paint_node_paint (iter);
}
if (res)
@ -1006,7 +1059,7 @@ clutter_paint_node_to_json (ClutterPaintNode *node)
if (node->operations != NULL)
{
guint i;
guint i, j;
for (i = 0; i < node->operations->len; i++)
{
@ -1031,6 +1084,19 @@ clutter_paint_node_to_json (ClutterPaintNode *node)
json_builder_end_array (builder);
break;
case PAINT_OP_MULTITEX_RECT:
json_builder_set_member_name (builder, "texrect");
json_builder_begin_array (builder);
for (j = 0; i < op->multitex_coords->len; j++)
{
float coord = g_array_index (op->multitex_coords, float, j);
json_builder_add_double_value (builder, coord);
}
json_builder_end_array (builder);
break;
case PAINT_OP_PATH:
json_builder_set_member_name (builder, "path");
json_builder_add_int_value (builder, (gint64) op->op.path);

View File

@ -49,6 +49,9 @@ ClutterPaintNode * clutter_paint_node_ref (Clutter
CLUTTER_EXPORT
void clutter_paint_node_unref (ClutterPaintNode *node);
CLUTTER_EXPORT
void clutter_paint_node_paint (ClutterPaintNode *node);
CLUTTER_EXPORT
void clutter_paint_node_set_name (ClutterPaintNode *node,
const char *name);
@ -67,6 +70,12 @@ void clutter_paint_node_add_texture_rectangle (Clutter
float x_2,
float y_2);
CLUTTER_EXPORT
void clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode *node,
const ClutterActorBox *rect,
const float *text_coords,
unsigned int text_coords_len);
CLUTTER_EXPORT
void clutter_paint_node_add_path (ClutterPaintNode *node,
CoglPath *path);

View File

@ -83,16 +83,13 @@ _clutter_paint_node_init_types (void)
}
/*
* Root node, private
* Root node
*
* any frame can only have a since RootNode instance for each
* top-level actor.
*/
#define clutter_root_node_get_type _clutter_root_node_get_type
typedef struct _ClutterRootNode ClutterRootNode;
typedef struct _ClutterPaintNodeClass ClutterRootNodeClass;
#define clutter_root_node_get_type clutter_root_node_get_type
struct _ClutterRootNode
{
@ -111,6 +108,8 @@ clutter_root_node_pre_draw (ClutterPaintNode *node)
{
ClutterRootNode *rnode = (ClutterRootNode *) node;
cogl_push_framebuffer (rnode->framebuffer);
cogl_framebuffer_clear (rnode->framebuffer,
rnode->clear_flags,
&rnode->clear_color);
@ -121,6 +120,7 @@ clutter_root_node_pre_draw (ClutterPaintNode *node)
static void
clutter_root_node_post_draw (ClutterPaintNode *node)
{
cogl_pop_framebuffer ();
}
static void
@ -158,13 +158,13 @@ clutter_root_node_init (ClutterRootNode *self)
}
ClutterPaintNode *
_clutter_root_node_new (CoglFramebuffer *framebuffer,
const ClutterColor *clear_color,
CoglBufferBit clear_flags)
clutter_root_node_new (CoglFramebuffer *framebuffer,
const ClutterColor *clear_color,
CoglBufferBit clear_flags)
{
ClutterRootNode *res;
res = _clutter_paint_node_create (_clutter_root_node_get_type ());
res = _clutter_paint_node_create (CLUTTER_TYPE_ROOT_NODE);
cogl_color_init_from_4ub (&res->clear_color,
clear_color->red,
@ -431,6 +431,17 @@ clutter_pipeline_node_draw (ClutterPaintNode *node)
op->op.texrect[7]);
break;
case PAINT_OP_MULTITEX_RECT:
cogl_framebuffer_draw_multitextured_rectangle (cogl_get_draw_framebuffer (),
pnode->pipeline,
op->op.texrect[0],
op->op.texrect[1],
op->op.texrect[2],
op->op.texrect[3],
(float*) op->multitex_coords->data,
op->multitex_coords->len);
break;
case PAINT_OP_PATH:
cogl_path_fill (op->op.path);
break;
@ -827,6 +838,7 @@ clutter_text_node_draw (ClutterPaintNode *node)
cogl_framebuffer_pop_clip (fb);
break;
case PAINT_OP_MULTITEX_RECT:
case PAINT_OP_PATH:
case PAINT_OP_PRIMITIVE:
case PAINT_OP_INVALID:
@ -992,6 +1004,7 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node)
retval = TRUE;
break;
case PAINT_OP_MULTITEX_RECT:
case PAINT_OP_PRIMITIVE:
case PAINT_OP_INVALID:
break;
@ -1025,6 +1038,7 @@ clutter_clip_node_post_draw (ClutterPaintNode *node)
cogl_framebuffer_pop_clip (fb);
break;
case PAINT_OP_MULTITEX_RECT:
case PAINT_OP_PRIMITIVE:
case PAINT_OP_INVALID:
break;
@ -1180,6 +1194,17 @@ clutter_layer_node_post_draw (ClutterPaintNode *node)
cogl_pop_source ();
break;
case PAINT_OP_MULTITEX_RECT:
cogl_framebuffer_draw_multitextured_rectangle (cogl_get_draw_framebuffer (),
lnode->state,
op->op.texrect[0],
op->op.texrect[1],
op->op.texrect[2],
op->op.texrect[3],
(float*) op->multitex_coords->data,
op->multitex_coords->len);
break;
case PAINT_OP_PATH:
cogl_push_source (lnode->state);
cogl_path_fill (op->op.path);

View File

@ -143,6 +143,26 @@ CLUTTER_EXPORT
ClutterPaintNode * clutter_text_node_new (PangoLayout *layout,
const ClutterColor *color);
#define CLUTTER_TYPE_ROOT_NODE (clutter_root_node_get_type ())
#define CLUTTER_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ROOT_NODE, ClutterRootNode))
#define CLUTTER_IS_ROOT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ROOT_NODE))
/**
* ClutterRootNode:
*
* The #ClutterRootNode structure is an opaque
* type whose members cannot be directly accessed.
*/
typedef struct _ClutterRootNode ClutterRootNode;
typedef struct _ClutterPaintNodeClass ClutterRootNodeClass;
CLUTTER_EXPORT
GType clutter_root_node_get_type (void) G_GNUC_CONST;
CLUTTER_EXPORT
ClutterPaintNode * clutter_root_node_new (CoglFramebuffer *framebuffer,
const ClutterColor *clear_color,
CoglBufferBit clear_flags);
G_END_DECLS
#endif /* __CLUTTER_PAINT_NODES_H__ */

View File

@ -35,6 +35,7 @@
#include "clutter-paint-volume-private.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-actor-box-private.h"
G_DEFINE_BOXED_TYPE (ClutterPaintVolume, clutter_paint_volume,
clutter_paint_volume_copy,
@ -1138,8 +1139,6 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
CoglMatrix modelview;
CoglMatrix projection;
float viewport[4];
float width;
float height;
_clutter_paint_volume_copy_static (pv, &projected_pv);
@ -1179,50 +1178,7 @@ _clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
return;
}
/* The aim here is that for a given rectangle defined with floating point
* coordinates we want to determine a stable quantized size in pixels
* that doesn't vary due to the original box's sub-pixel position.
*
* The reason this is important is because effects will use this
* API to determine the size of offscreen framebuffers and so for
* a fixed-size object that may be animated accross the screen we
* want to make sure that the stage paint-box has an equally stable
* size so that effects aren't made to continuously re-allocate
* a corresponding fbo.
*
* The other thing we consider is that the calculation of this box is
* subject to floating point precision issues that might be slightly
* different to the precision issues involved with actually painting the
* actor, which might result in painting slightly leaking outside the
* user's calculated paint-volume. For this we simply aim to pad out the
* paint-volume by at least half a pixel all the way around.
*/
width = box->x2 - box->x1;
height = box->y2 - box->y1;
width = CLUTTER_NEARBYINT (width);
height = CLUTTER_NEARBYINT (height);
/* XXX: NB the width/height may now be up to 0.5px too small so we
* must also pad by 0.25px all around to account for this. In total we
* must padd by at least 0.75px around all sides. */
/* XXX: The furthest that we can overshoot the bottom right corner by
* here is 1.75px in total if you consider that the 0.75 padding could
* just cross an integer boundary and so ceil will effectively add 1.
*/
box->x2 = ceilf (box->x2 + 0.75);
box->y2 = ceilf (box->y2 + 0.75);
/* Now we redefine the top-left relative to the bottom right based on the
* rounded width/height determined above + a constant so that the overall
* size of the box will be stable and not dependant on the box's
* position.
*
* Adding 3px to the width/height will ensure we cover the maximum of
* 1.75px padding on the bottom/right and still ensure we have > 0.75px
* padding on the top/left.
*/
box->x1 = box->x2 - width - 3;
box->y1 = box->y2 - height - 3;
_clutter_actor_box_enlarge_for_effects (box);
clutter_paint_volume_free (&projected_pv);
}

View File

@ -961,6 +961,7 @@ clutter_pan_action_get_motion_delta (ClutterPanAction *self,
return clutter_pan_action_get_interpolated_delta (self, delta_x, delta_y);
default:
g_assert_not_reached ();
return 0.0f;
}
}

View File

@ -69,6 +69,9 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#define CLUTTER_ACTOR_IN_REPARENT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_REPARENT) != FALSE)
#define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE)
#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_WIDTH(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_WIDTH) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_HEIGHT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_HEIGHT) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_SIZE(a) ((CLUTTER_PRIVATE_FLAGS (a) & (CLUTTER_IN_PREF_HEIGHT|CLUTTER_IN_PREF_WIDTH)) != FALSE)
#define CLUTTER_PARAM_READABLE (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)
#define CLUTTER_PARAM_WRITABLE (G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
@ -91,21 +94,24 @@ typedef struct _ClutterVertex4 ClutterVertex4;
* because it will break for negative numbers. */
#define CLUTTER_NEARBYINT(x) ((int) ((x) < 0.0f ? (x) - 0.5f : (x) + 0.5f))
typedef enum {
typedef enum
{
CLUTTER_ACTOR_UNUSED_FLAG = 0,
CLUTTER_IN_DESTRUCTION = 1 << 0,
CLUTTER_IS_TOPLEVEL = 1 << 1,
CLUTTER_IN_REPARENT = 1 << 2,
CLUTTER_IN_PREF_WIDTH = 1 << 3,
CLUTTER_IN_PREF_HEIGHT = 1 << 4,
/* Used to avoid recursion */
CLUTTER_IN_PAINT = 1 << 3,
CLUTTER_IN_PAINT = 1 << 5,
/* Used to avoid recursion */
CLUTTER_IN_RELAYOUT = 1 << 4,
CLUTTER_IN_RELAYOUT = 1 << 6,
/* a flag for internal children of Containers (DEPRECATED) */
CLUTTER_INTERNAL_CHILD = 1 << 5
CLUTTER_INTERNAL_CHILD = 1 << 7
} ClutterPrivateFlags;
/*
@ -202,7 +208,7 @@ gboolean _clutter_feature_init (GError **error);
/* Diagnostic mode */
gboolean _clutter_diagnostic_enabled (void);
void _clutter_diagnostic_message (const char *fmt, ...);
void _clutter_diagnostic_message (const char *fmt, ...) G_GNUC_PRINTF (1, 2);
/* Picking code */
guint _clutter_pixel_to_id (guchar pixel[4]);
@ -240,6 +246,17 @@ void _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
ClutterVertex *vertices_out,
int n_vertices);
void _clutter_util_rect_from_rectangle (const cairo_rectangle_int_t *src,
ClutterRect *dest);
void _clutter_util_rectangle_int_extents (const ClutterRect *src,
cairo_rectangle_int_t *dest);
void _clutter_util_rectangle_offset (const cairo_rectangle_int_t *src,
int x,
int y,
cairo_rectangle_int_t *dest);
void _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1,
const cairo_rectangle_int_t *src2,
cairo_rectangle_int_t *dest);

View File

@ -79,7 +79,8 @@ typedef void (* ClutterScriptConnectFunc) (ClutterScript *script,
*
* Since: 0.6
*/
typedef enum {
typedef enum
{
CLUTTER_SCRIPT_ERROR_INVALID_TYPE_FUNCTION,
CLUTTER_SCRIPT_ERROR_INVALID_PROPERTY,
CLUTTER_SCRIPT_ERROR_INVALID_VALUE

View File

@ -84,9 +84,9 @@ enum
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
static GParamSpec *animatable_props[ANIM_PROP_LAST] = { NULL, };
static ClutterAnimatableIface *parent_animatable_iface = NULL;
static ClutterAnimatableInterface *parent_animatable_iface = NULL;
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
static void clutter_animatable_iface_init (ClutterAnimatableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterScrollActor, clutter_scroll_actor, CLUTTER_TYPE_ACTOR,
G_ADD_PRIVATE (ClutterScrollActor)
@ -240,7 +240,7 @@ clutter_scroll_actor_get_initial_state (ClutterAnimatable *animatable,
}
static void
clutter_animatable_iface_init (ClutterAnimatableIface *iface)
clutter_animatable_iface_init (ClutterAnimatableInterface *iface)
{
parent_animatable_iface = g_type_interface_peek_parent (iface);

View File

@ -333,6 +333,7 @@ clutter_shader_effect_create_shader (ClutterShaderEffect *self)
default:
g_assert_not_reached ();
return COGL_INVALID_HANDLE;
}
}

View File

@ -124,11 +124,16 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
void _clutter_stage_set_scale_factor (ClutterStage *stage,
int factor);
gboolean _clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
ClutterRect *rect,
float *view_scale);
void _clutter_stage_presented (ClutterStage *stage,
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info);
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View File

@ -14,10 +14,6 @@
* #ClutterStage actor, abstracting away the specifics of the windowing system.
*/
#define clutter_stage_window_get_type _clutter_stage_window_get_type
typedef ClutterStageWindowIface ClutterStageWindowInterface;
G_DEFINE_INTERFACE (ClutterStageWindow, clutter_stage_window, G_TYPE_OBJECT);
static void
@ -60,7 +56,7 @@ void
_clutter_stage_window_set_title (ClutterStageWindow *window,
const gchar *title)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->set_title)
iface->set_title (window, title);
@ -70,7 +66,7 @@ void
_clutter_stage_window_set_fullscreen (ClutterStageWindow *window,
gboolean is_fullscreen)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->set_fullscreen)
iface->set_fullscreen (window, is_fullscreen);
@ -80,7 +76,7 @@ void
_clutter_stage_window_set_cursor_visible (ClutterStageWindow *window,
gboolean is_visible)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->set_cursor_visible)
iface->set_cursor_visible (window, is_visible);
@ -138,7 +134,7 @@ void
_clutter_stage_window_schedule_update (ClutterStageWindow *window,
int sync_delay)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
@ -163,7 +159,7 @@ _clutter_stage_window_schedule_update (ClutterStageWindow *window,
gint64
_clutter_stage_window_get_update_time (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0);
@ -186,7 +182,7 @@ _clutter_stage_window_get_update_time (ClutterStageWindow *window)
void
_clutter_stage_window_clear_update_time (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
@ -204,7 +200,7 @@ void
_clutter_stage_window_add_redraw_clip (ClutterStageWindow *window,
cairo_rectangle_int_t *stage_clip)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
@ -224,7 +220,7 @@ _clutter_stage_window_add_redraw_clip (ClutterStageWindow *window,
gboolean
_clutter_stage_window_has_redraw_clips (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
@ -246,7 +242,7 @@ _clutter_stage_window_has_redraw_clips (ClutterStageWindow *window)
gboolean
_clutter_stage_window_ignoring_redraw_clips (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
@ -261,7 +257,7 @@ gboolean
_clutter_stage_window_get_redraw_clip_bounds (ClutterStageWindow *window,
cairo_rectangle_int_t *stage_clip)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
@ -276,7 +272,7 @@ void
_clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
gboolean accept_focus)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
@ -288,7 +284,7 @@ _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
void
_clutter_stage_window_redraw (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
@ -303,7 +299,7 @@ _clutter_stage_window_get_dirty_pixel (ClutterStageWindow *window,
ClutterStageView *view,
int *x, int *y)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
*x = 0;
*y = 0;
@ -318,7 +314,7 @@ _clutter_stage_window_get_dirty_pixel (ClutterStageWindow *window,
gboolean
_clutter_stage_window_can_clip_redraws (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), FALSE);
@ -332,7 +328,7 @@ _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window)
GList *
_clutter_stage_window_get_views (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
return iface->get_views (window);
}
@ -340,7 +336,7 @@ _clutter_stage_window_get_views (ClutterStageWindow *window)
void
_clutter_stage_window_finish_frame (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->finish_frame)
iface->finish_frame (window);
@ -349,7 +345,7 @@ _clutter_stage_window_finish_frame (ClutterStageWindow *window)
int64_t
_clutter_stage_window_get_frame_counter (ClutterStageWindow *window)
{
ClutterStageWindowIface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
if (iface->get_frame_counter)
return iface->get_frame_counter (window);

View File

@ -7,30 +7,21 @@
G_BEGIN_DECLS
#define CLUTTER_TYPE_STAGE_WINDOW (_clutter_stage_window_get_type ())
#define CLUTTER_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindow))
#define CLUTTER_IS_STAGE_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_WINDOW))
#define CLUTTER_STAGE_WINDOW_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_STAGE_WINDOW, ClutterStageWindowIface))
#define CLUTTER_TYPE_STAGE_WINDOW (clutter_stage_window_get_type ())
CLUTTER_EXPORT
G_DECLARE_INTERFACE (ClutterStageWindow, clutter_stage_window,
CLUTTER, STAGE_WINDOW,
GObject)
/*
* ClutterStageWindow: (skip)
*
* #ClutterStageWindow is an opaque structure
* whose members should not be accessed directly
*
* Since: 0.8
*/
typedef struct _ClutterStageWindow ClutterStageWindow; /* dummy */
typedef struct _ClutterStageWindowIface ClutterStageWindowIface;
/*
* ClutterStageWindowIface: (skip)
* ClutterStageWindowInterface: (skip)
*
* The interface implemented by backends for stage windows
*
* Since: 0.8
*/
struct _ClutterStageWindowIface
struct _ClutterStageWindowInterface
{
/*< private >*/
GTypeInterface parent_iface;
@ -88,9 +79,6 @@ struct _ClutterStageWindowIface
void (* finish_frame) (ClutterStageWindow *stage_window);
};
CLUTTER_EXPORT
GType _clutter_stage_window_get_type (void) G_GNUC_CONST;
ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window);
void _clutter_stage_window_set_title (ClutterStageWindow *window,

View File

@ -87,7 +87,8 @@
*
* A series of hints that enable or disable behaviours on the stage
*/
typedef enum { /*< prefix=CLUTTER_STAGE >*/
typedef enum /*< prefix=CLUTTER_STAGE >*/
{
CLUTTER_STAGE_HINT_NONE = 0,
CLUTTER_STAGE_NO_CLEAR_ON_PAINT = 1 << 0
@ -201,6 +202,12 @@ static const ClutterColor default_stage_color = { 255, 255, 255, 255 };
static void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
static void free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry);
static void capture_view_into (ClutterStage *stage,
gboolean paint,
ClutterStageView *view,
cairo_rectangle_int_t *rect,
uint8_t *data,
int stride);
static void clutter_container_iface_init (ClutterContainerIface *iface);
@ -1274,45 +1281,44 @@ clutter_stage_real_queue_relayout (ClutterActor *self)
parent_class->queue_relayout (self);
}
static void
clutter_stage_real_queue_redraw (ClutterActor *actor,
ClutterActor *leaf)
static gboolean
clutter_stage_real_queue_redraw (ClutterActor *actor,
ClutterActor *leaf,
ClutterPaintVolume *redraw_clip)
{
ClutterStage *stage = CLUTTER_STAGE (actor);
ClutterStageWindow *stage_window;
ClutterPaintVolume *redraw_clip;
ClutterActorBox bounding_box;
ClutterActorBox intersection_box;
cairo_rectangle_int_t geom, stage_clip;
if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
return;
return TRUE;
/* If the backend can't do anything with redraw clips (e.g. it already knows
* it needs to redraw everything anyway) then don't spend time transforming
* any clip volume into stage coordinates... */
stage_window = _clutter_stage_get_window (stage);
if (stage_window == NULL)
return;
return TRUE;
if (_clutter_stage_window_ignoring_redraw_clips (stage_window))
{
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
return;
return FALSE;
}
/* Convert the clip volume into stage coordinates and then into an
* axis aligned stage coordinates bounding box...
*/
redraw_clip = _clutter_actor_get_queue_redraw_clip (leaf);
if (redraw_clip == NULL)
{
_clutter_stage_window_add_redraw_clip (stage_window, NULL);
return;
return FALSE;
}
if (redraw_clip->is_empty)
return;
return TRUE;
_clutter_paint_volume_get_stage_paint_box (redraw_clip,
stage,
@ -1328,7 +1334,7 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
/* There is no need to track degenerate/empty redraw clips */
if (intersection_box.x2 <= intersection_box.x1 ||
intersection_box.y2 <= intersection_box.y1)
return;
return TRUE;
/* when converting to integer coordinates make sure we round the edges of the
* clip rectangle outwards... */
@ -1338,6 +1344,7 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
stage_clip.height = intersection_box.y2 - stage_clip.y;
_clutter_stage_window_add_redraw_clip (stage_window, &stage_clip);
return FALSE;
}
gboolean
@ -1474,8 +1481,8 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS)))
{
CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1",
(int) dirty_x * fb_scale,
(int) dirty_y * fb_scale);
(int) (dirty_x * fb_scale),
(int) (dirty_y * fb_scale));
cogl_framebuffer_push_scissor_clip (fb, dirty_x * fb_scale, dirty_y * fb_scale, 1, 1);
}
@ -1495,7 +1502,7 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
read_x = dirty_x * fb_scale;
read_y = dirty_y * fb_scale;
CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d s: %d",
CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d s: %f",
x, y,
view_layout.width, view_layout.height,
view_layout.x, view_layout.y, fb_scale);
@ -2742,7 +2749,7 @@ clutter_stage_set_fullscreen (ClutterStage *stage,
if (priv->is_fullscreen != fullscreen)
{
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
@ -2807,7 +2814,7 @@ clutter_stage_set_user_resizable (ClutterStage *stage,
&& priv->is_user_resizable != resizable)
{
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
if (iface->set_user_resizable)
@ -2856,7 +2863,7 @@ clutter_stage_show_cursor (ClutterStage *stage)
if (!priv->is_cursor_visible)
{
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
if (iface->set_cursor_visible)
@ -2889,7 +2896,7 @@ clutter_stage_hide_cursor (ClutterStage *stage)
if (priv->is_cursor_visible)
{
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
ClutterStageWindowIface *iface;
ClutterStageWindowInterface *iface;
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
if (iface->set_cursor_visible)
@ -2937,6 +2944,9 @@ clutter_stage_read_pixels (ClutterStage *stage,
cairo_region_t *clip;
cairo_rectangle_int_t clip_rect;
CoglFramebuffer *framebuffer;
float view_scale;
float pixel_width;
float pixel_height;
uint8_t *pixels;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
@ -2979,10 +2989,15 @@ clutter_stage_read_pixels (ClutterStage *stage,
cogl_push_framebuffer (framebuffer);
clutter_stage_do_paint_view (stage, view, &clip_rect);
pixels = g_malloc0 (clip_rect.width * clip_rect.height * 4);
view_scale = clutter_stage_view_get_scale (view);
pixel_width = roundf (clip_rect.width * view_scale);
pixel_height = roundf (clip_rect.height * view_scale);
pixels = g_malloc0 (pixel_width * pixel_height * 4);
cogl_framebuffer_read_pixels (framebuffer,
clip_rect.x, clip_rect.y,
clip_rect.width, clip_rect.height,
clip_rect.x * view_scale,
clip_rect.y * view_scale,
pixel_width, pixel_height,
COGL_PIXEL_FORMAT_RGBA_8888,
pixels);
@ -4756,62 +4771,33 @@ static void
capture_view (ClutterStage *stage,
gboolean paint,
ClutterStageView *view,
cairo_rectangle_int_t *rect,
ClutterCapture *capture)
{
CoglFramebuffer *framebuffer;
ClutterBackend *backend;
CoglContext *context;
cairo_surface_t *image;
uint8_t *data;
int stride;
CoglBitmap *bitmap;
cairo_rectangle_int_t view_layout;
cairo_rectangle_int_t *rect;
float view_scale;
float texture_width;
float texture_height;
framebuffer = clutter_stage_view_get_framebuffer (view);
if (paint)
{
cogl_push_framebuffer (framebuffer);
_clutter_stage_maybe_setup_viewport (stage, view);
clutter_stage_do_paint_view (stage, view, rect);
}
rect = &capture->rect;
view_scale = clutter_stage_view_get_scale (view);
texture_width = roundf (rect->width * view_scale);
texture_height = roundf (rect->height * view_scale);
image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
rect->width * view_scale,
rect->height * view_scale);
texture_width, texture_height);
cairo_surface_set_device_scale (image, view_scale, view_scale);
data = cairo_image_surface_get_data (image);
stride = cairo_image_surface_get_stride (image);
backend = clutter_get_default_backend ();
context = clutter_backend_get_cogl_context (backend);
bitmap = cogl_bitmap_new_for_data (context,
rect->width * view_scale,
rect->height * view_scale,
CLUTTER_CAIRO_FORMAT_ARGB32,
stride,
data);
clutter_stage_view_get_layout (view, &view_layout);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
(rect->x - view_layout.x) * view_scale,
(rect->y - view_layout.y) * view_scale,
COGL_READ_PIXELS_COLOR_BUFFER,
bitmap);
if (paint)
cogl_pop_framebuffer ();
capture->rect = *rect;
capture_view_into (stage, paint, view, rect, data, stride);
capture->image = image;
cairo_surface_mark_dirty (capture->image);
cogl_object_unref (bitmap);
}
gboolean
@ -4827,34 +4813,91 @@ clutter_stage_capture (ClutterStage *stage,
ClutterCapture *captures;
int n_captures;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
captures = g_new0 (ClutterCapture, g_list_length (views));
n_captures = 0;
for (l = views; l; l = l->next)
{
ClutterStageView *view = l->data;
ClutterCapture *capture;
cairo_rectangle_int_t view_layout;
cairo_region_t *region;
cairo_rectangle_int_t view_capture_rect;
clutter_stage_view_get_layout (view, &view_layout);
region = cairo_region_create_rectangle (&view_layout);
cairo_region_intersect_rectangle (region, rect);
cairo_region_get_extents (region, &view_capture_rect);
capture = &captures[n_captures];
cairo_region_get_extents (region, &capture->rect);
cairo_region_destroy (region);
if (view_capture_rect.width == 0 || view_capture_rect.height == 0)
if (capture->rect.width == 0 || capture->rect.height == 0)
continue;
capture_view (stage, paint, view, &view_capture_rect,
&captures[n_captures]);
capture_view (stage, paint, view, capture);
n_captures++;
}
if (n_captures == 0)
g_clear_pointer (&captures, g_free);
*out_captures = captures;
*out_n_captures = n_captures;
return n_captures > 0;
}
gboolean
clutter_stage_get_capture_final_size (ClutterStage *stage,
cairo_rectangle_int_t *rect,
int *out_width,
int *out_height,
float *out_scale)
{
float max_scale;
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
if (rect)
{
ClutterRect capture_rect;
_clutter_util_rect_from_rectangle (rect, &capture_rect);
if (!_clutter_stage_get_max_view_scale_factor_for_rect (stage,
&capture_rect,
&max_scale))
return FALSE;
if (out_width)
*out_width = (gint) roundf (rect->width * max_scale);
if (out_height)
*out_height = (gint) roundf (rect->height * max_scale);
}
else
{
ClutterActorBox alloc;
float stage_width, stage_height;
clutter_actor_get_allocation_box (CLUTTER_ACTOR (stage), &alloc);
clutter_actor_box_get_size (&alloc, &stage_width, &stage_height);
if (!_clutter_actor_get_real_resource_scale (CLUTTER_ACTOR (stage),
&max_scale))
return FALSE;
if (out_width)
*out_width = (gint) roundf (stage_width * max_scale);
if (out_height)
*out_height = (gint) roundf (stage_height * max_scale);
}
if (out_scale)
*out_scale = max_scale;
return TRUE;
}
@ -4871,6 +4914,11 @@ capture_view_into (ClutterStage *stage,
CoglContext *context;
CoglBitmap *bitmap;
cairo_rectangle_int_t view_layout;
float view_scale;
float texture_width;
float texture_height;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
framebuffer = clutter_stage_view_get_framebuffer (view);
@ -4881,10 +4929,14 @@ capture_view_into (ClutterStage *stage,
clutter_stage_do_paint_view (stage, view, rect);
}
view_scale = clutter_stage_view_get_scale (view);
texture_width = roundf (rect->width * view_scale);
texture_height = roundf (rect->height * view_scale);
backend = clutter_get_default_backend ();
context = clutter_backend_get_cogl_context (backend);
bitmap = cogl_bitmap_new_for_data (context,
rect->width, rect->height,
texture_width, texture_height,
CLUTTER_CAIRO_FORMAT_ARGB32,
stride,
data);
@ -4892,8 +4944,8 @@ capture_view_into (ClutterStage *stage,
clutter_stage_view_get_layout (view, &view_layout);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
rect->x - view_layout.x,
rect->y - view_layout.y,
roundf ((rect->x - view_layout.x) * view_scale),
roundf ((rect->y - view_layout.y) * view_scale),
COGL_READ_PIXELS_COLOR_BUFFER,
bitmap);
@ -5002,3 +5054,46 @@ clutter_stage_thaw_updates (ClutterStage *stage)
_clutter_master_clock_set_paused (master_clock, FALSE);
}
}
GList *
_clutter_stage_peek_stage_views (ClutterStage *stage)
{
ClutterStagePrivate *priv = stage->priv;
return _clutter_stage_window_get_views (priv->impl);
}
void
clutter_stage_update_resource_scales (ClutterStage *stage)
{
_clutter_actor_queue_update_resource_scale_recursive (CLUTTER_ACTOR (stage));
}
gboolean
_clutter_stage_get_max_view_scale_factor_for_rect (ClutterStage *stage,
ClutterRect *rect,
float *view_scale)
{
ClutterStagePrivate *priv = stage->priv;
float scale = 0.0f;
GList *l;
for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next)
{
ClutterStageView *view = l->data;
cairo_rectangle_int_t view_layout;
ClutterRect view_rect;
clutter_stage_view_get_layout (view, &view_layout);
_clutter_util_rect_from_rectangle (&view_layout, &view_rect);
if (clutter_rect_intersection (&view_rect, rect, NULL))
scale = MAX (clutter_stage_view_get_scale (view), scale);
}
if (scale == 0.0)
return FALSE;
*view_scale = scale;
return TRUE;
}

View File

@ -261,6 +261,13 @@ CLUTTER_EXPORT
void clutter_stage_skip_sync_delay (ClutterStage *stage);
#endif
CLUTTER_EXPORT
gboolean clutter_stage_get_capture_final_size (ClutterStage *stage,
cairo_rectangle_int_t *rect,
int *width,
int *height,
float *scale);
CLUTTER_EXPORT
gboolean clutter_stage_capture (ClutterStage *stage,
gboolean paint,

View File

@ -50,7 +50,8 @@
/* Initial size of buffer, in bytes */
#define MIN_SIZE 16
enum {
enum
{
PROP_0,
PROP_TEXT,
PROP_LENGTH,
@ -60,7 +61,8 @@ enum {
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
enum {
enum
{
INSERTED_TEXT,
DELETED_TEXT,
LAST_SIGNAL

View File

@ -144,15 +144,17 @@ struct _ClutterTextPrivate
*/
gint x_pos;
/* the x position of the PangoLayout when in
* single line mode, to scroll the contents of the
/* the x position of the PangoLayout (in both physical and logical pixels)
* when in single line mode, to scroll the contents of the
* text actor
*/
gint text_x;
gint text_logical_x;
/* the y position of the PangoLayout, fixed to 0 by
* default for now */
/* the y position of the PangoLayout (in both physical and logical pixels),
* fixed to 0 by default for now */
gint text_y;
gint text_logical_y;
/* Where to draw the cursor */
ClutterRect cursor_rect;
@ -185,6 +187,9 @@ struct _ClutterTextPrivate
ClutterInputContentHintFlags input_hints;
ClutterInputContentPurpose input_purpose;
/* Signal handler for when the :resource-scale changes */
guint resource_scale_changed_id;
/* bitfields */
guint alignment : 2;
guint wrap : 1;
@ -279,7 +284,7 @@ static const ClutterColor default_selected_text_color = { 0, 0, 0, 255 };
static CoglPipeline *default_color_pipeline = NULL;
static ClutterAnimatableIface *parent_animatable_iface = NULL;
static ClutterAnimatableInterface *parent_animatable_iface = NULL;
static ClutterScriptableIface *parent_scriptable_iface = NULL;
/* ClutterTextInputFocus */
@ -290,6 +295,33 @@ G_DECLARE_FINAL_TYPE (ClutterTextInputFocus, clutter_text_input_focus,
G_DEFINE_TYPE (ClutterTextInputFocus, clutter_text_input_focus,
CLUTTER_TYPE_INPUT_FOCUS)
/* Utilities pango to (logical) pixels functions */
static float
pixels_to_pango (float px)
{
return ceilf (px * (float) PANGO_SCALE);
}
static float
logical_pixels_to_pango (float px,
float scale)
{
return pixels_to_pango (px * scale);
}
static float
pango_to_pixels (float size)
{
return ceilf (size / (float) PANGO_SCALE);
}
static float
pango_to_logical_pixels (float size,
float scale)
{
return pango_to_pixels (size / scale);
}
static void
clutter_text_input_focus_request_surrounding (ClutterInputFocus *focus)
{
@ -389,7 +421,7 @@ clutter_text_input_focus_new (ClutterText *text)
/* ClutterText */
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
static void clutter_animatable_iface_init (ClutterAnimatableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterText,
clutter_text,
@ -550,6 +582,63 @@ clutter_text_get_display_text (ClutterText *self)
}
}
static void
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;
if (priv->effective_attrs != NULL)
{
PangoAttrIterator *iter;
PangoAttribute *scale_attrib;
PangoAttrList *old_attributes;
old_attributes = priv->effective_attrs;
priv->effective_attrs = pango_attr_list_copy (priv->effective_attrs);
pango_attr_list_unref (old_attributes);
iter = pango_attr_list_get_iterator (priv->effective_attrs);
scale_attrib = pango_attr_iterator_get (iter, PANGO_ATTR_SCALE);
if (scale_attrib != NULL)
resource_scale *= ((PangoAttrFloat *) scale_attrib)->value;
pango_attr_iterator_destroy (iter);
}
else
priv->effective_attrs = pango_attr_list_new ();
pango_attr_list_change (priv->effective_attrs,
pango_attr_scale_new (resource_scale));
}
static void
set_effective_pango_attributes (ClutterText *self,
PangoAttrList *attributes)
{
ClutterTextPrivate *priv = self->priv;
if (attributes != NULL)
{
PangoAttrList *old_attributes = priv->effective_attrs;
priv->effective_attrs = pango_attr_list_ref (attributes);
if (old_attributes != NULL)
pango_attr_list_unref (old_attributes);
}
else
{
g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref);
}
ensure_effective_pango_scale_attribute (self);
}
static inline void
clutter_text_ensure_effective_attributes (ClutterText *self)
{
@ -563,21 +652,25 @@ clutter_text_ensure_effective_attributes (ClutterText *self)
/* Same as if we don't have any attribute at all.
* We also ignore markup attributes for editable. */
if (priv->attrs == NULL && (priv->editable || priv->markup_attrs == NULL))
return;
{
set_effective_pango_attributes (self, NULL);
return;
}
if (priv->attrs != NULL)
{
/* If there are no markup attributes, or if this is editable (in which
* case we ignore markup), then we can just use these attrs directly */
if (priv->editable || priv->markup_attrs == NULL)
priv->effective_attrs = pango_attr_list_ref (priv->attrs);
set_effective_pango_attributes (self, priv->attrs);
else
{
/* Otherwise we need to merge the two lists */
PangoAttrList *effective_attrs;
PangoAttrIterator *iter;
GSList *attributes, *l;
priv->effective_attrs = pango_attr_list_copy (priv->markup_attrs);
effective_attrs = pango_attr_list_copy (priv->markup_attrs);
iter = pango_attr_list_get_iterator (priv->attrs);
do
@ -588,7 +681,7 @@ clutter_text_ensure_effective_attributes (ClutterText *self)
{
PangoAttribute *attr = l->data;
pango_attr_list_insert (priv->effective_attrs, attr);
pango_attr_list_insert (effective_attrs, attr);
}
g_slist_free (attributes);
@ -596,12 +689,14 @@ clutter_text_ensure_effective_attributes (ClutterText *self)
while (pango_attr_iterator_next (iter));
pango_attr_iterator_destroy (iter);
set_effective_pango_attributes (self, effective_attrs);
pango_attr_list_unref (effective_attrs);
}
}
else if (priv->markup_attrs != NULL)
{
/* We can just use the markup attributes directly */
priv->effective_attrs = pango_attr_list_ref (priv->markup_attrs);
set_effective_pango_attributes (self, priv->markup_attrs);
}
}
@ -810,6 +905,18 @@ 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
@ -877,7 +984,7 @@ clutter_text_create_layout (ClutterText *text,
!((priv->editable && priv->single_line_mode) ||
(priv->ellipsize == PANGO_ELLIPSIZE_NONE && !priv->wrap))))
{
width = allocation_width * 1024 + 0.5f;
width = pixels_to_pango (allocation_width);
}
/* Pango only uses height if ellipsization is enabled, so don't set
@ -894,7 +1001,7 @@ clutter_text_create_layout (ClutterText *text,
priv->ellipsize != PANGO_ELLIPSIZE_NONE &&
!priv->single_line_mode)
{
height = allocation_height * 1024 + 0.5f;
height = pixels_to_pango (allocation_height);
}
/* Search for a cached layout with the same width and keep
@ -991,6 +1098,37 @@ clutter_text_create_layout (ClutterText *text,
return oldest_cache->layout;
}
static PangoLayout *
create_text_layout_with_scale (ClutterText *text,
gfloat allocation_width,
gfloat allocation_height,
gfloat scale)
{
if (allocation_width > 0)
allocation_width = roundf (allocation_width * scale);
if (allocation_height > 0)
allocation_height = roundf (allocation_height * scale);
return clutter_text_create_layout (text, allocation_width, allocation_height);
}
static PangoLayout *
maybe_create_text_layout_with_resource_scale (ClutterText *text,
gfloat allocation_width,
gfloat allocation_height)
{
float resource_scale;
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale))
return NULL;
return create_text_layout_with_scale (text,
allocation_width,
allocation_height,
resource_scale);
}
/**
* clutter_text_coords_to_position:
* @self: a #ClutterText
@ -1011,14 +1149,18 @@ clutter_text_coords_to_position (ClutterText *self,
gint index_;
gint px, py;
gint trailing;
gfloat resource_scale;
g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0);
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return 0;
/* Take any offset due to scrolling into account, and normalize
* the coordinates to PangoScale units
*/
px = (x - self->priv->text_x) * PANGO_SCALE;
py = (y - self->priv->text_y) * PANGO_SCALE;
px = logical_pixels_to_pango (x - self->priv->text_logical_x, resource_scale);
py = logical_pixels_to_pango (y - self->priv->text_logical_y, resource_scale);
pango_layout_xy_to_index (clutter_text_get_layout (self),
px, py,
@ -1027,26 +1169,12 @@ clutter_text_coords_to_position (ClutterText *self,
return index_ + trailing;
}
/**
* clutter_text_position_to_coords:
* @self: a #ClutterText
* @position: position in characters
* @x: (out): return location for the X coordinate, or %NULL
* @y: (out): return location for the Y coordinate, or %NULL
* @line_height: (out): return location for the line height, or %NULL
*
* Retrieves the coordinates of the given @position.
*
* Return value: %TRUE if the conversion was successful
*
* Since: 1.0
*/
gboolean
clutter_text_position_to_coords (ClutterText *self,
gint position,
gfloat *x,
gfloat *y,
gfloat *line_height)
static gboolean
clutter_text_position_to_coords_internal (ClutterText *self,
gint position,
gfloat *x,
gfloat *y,
gfloat *line_height)
{
ClutterTextPrivate *priv;
PangoRectangle rect;
@ -1112,7 +1240,7 @@ clutter_text_position_to_coords (ClutterText *self,
if (x)
{
*x = (gfloat) rect.x / 1024.0f;
*x = pango_to_pixels (rect.x);
/* Take any offset due to scrolling into account */
if (priv->single_line_mode)
@ -1120,14 +1248,58 @@ clutter_text_position_to_coords (ClutterText *self,
}
if (y)
*y = (gfloat) rect.y / 1024.0f;
*y = pango_to_pixels (rect.y);
if (line_height)
*line_height = (gfloat) rect.height / 1024.0f;
*line_height = pango_to_pixels (rect.height);
return TRUE;
}
/**
* clutter_text_position_to_coords:
* @self: a #ClutterText
* @position: position in characters
* @x: (out): return location for the X coordinate, or %NULL
* @y: (out): return location for the Y coordinate, or %NULL
* @line_height: (out): return location for the line height, or %NULL
*
* Retrieves the coordinates of the given @position.
*
* Return value: %TRUE if the conversion was successful
*
* Since: 1.0
*/
gboolean
clutter_text_position_to_coords (ClutterText *self,
gint position,
gfloat *x,
gfloat *y,
gfloat *line_height)
{
gfloat resource_scale;
gboolean ret;
g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE);
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return FALSE;
ret = clutter_text_position_to_coords_internal (self, position,
x, y, line_height);
if (x)
*x /= resource_scale;
if (y)
*y /= resource_scale;
if (line_height)
*line_height /= resource_scale;
return ret;
}
static inline void
update_cursor_location (ClutterText *self)
{
@ -1145,7 +1317,8 @@ update_cursor_location (ClutterText *self)
}
static inline void
clutter_text_ensure_cursor_position (ClutterText *self)
clutter_text_ensure_cursor_position (ClutterText *self,
float scale)
{
ClutterTextPrivate *priv = self->priv;
gfloat x, y, cursor_height;
@ -1168,15 +1341,15 @@ clutter_text_ensure_cursor_position (ClutterText *self)
priv->preedit_set ? priv->preedit_cursor_pos : 0);
x = y = cursor_height = 0;
clutter_text_position_to_coords (self, position,
&x, &y,
&cursor_height);
clutter_text_position_to_coords_internal (self, position,
&x, &y,
&cursor_height);
clutter_rect_init (&cursor_rect,
x,
y + CURSOR_Y_PADDING,
priv->cursor_size,
cursor_height - 2 * CURSOR_Y_PADDING);
y + CURSOR_Y_PADDING * scale,
priv->cursor_size * scale,
cursor_height - 2 * CURSOR_Y_PADDING * scale);
if (!clutter_rect_equals (&priv->cursor_rect, &cursor_rect))
{
@ -1599,6 +1772,12 @@ clutter_text_dispose (GObject *gobject)
priv->direction_changed_id = 0;
}
if (priv->resource_scale_changed_id)
{
g_signal_handler_disconnect (self, priv->resource_scale_changed_id);
priv->resource_scale_changed_id = 0;
}
if (priv->settings_changed_id)
{
g_signal_handler_disconnect (clutter_get_default_backend (),
@ -1651,6 +1830,7 @@ typedef void (* ClutterTextSelectionFunc) (ClutterText *text,
static void
clutter_text_foreach_selection_rectangle (ClutterText *self,
float scale,
ClutterTextSelectionFunc func,
gpointer user_data)
{
@ -1702,9 +1882,9 @@ clutter_text_foreach_selection_rectangle (ClutterText *self,
&n_ranges);
pango_layout_line_x_to_index (line, 0, &index_, NULL);
clutter_text_position_to_coords (self,
bytes_to_offset (utf8, index_),
NULL, &y, &height);
clutter_text_position_to_coords_internal (self,
bytes_to_offset (utf8, index_),
NULL, &y, &height);
box.y1 = y;
box.y2 = y + height;
@ -1714,18 +1894,18 @@ clutter_text_foreach_selection_rectangle (ClutterText *self,
gfloat range_x;
gfloat range_width;
range_x = ranges[i * 2] / PANGO_SCALE;
range_x = pango_to_pixels (ranges[i * 2]);
/* Account for any scrolling in single line mode */
if (priv->single_line_mode)
range_x += priv->text_x;
range_width = ((gfloat) ranges[i * 2 + 1] - (gfloat) ranges[i * 2])
/ PANGO_SCALE;
range_width = pango_to_pixels (ranges[i * 2 + 1] - ranges[i * 2]);
box.x1 = range_x;
box.x2 = ceilf (range_x + range_width + .5f);
box.x2 = ceilf (range_x + range_width);
clutter_actor_box_scale (&box, scale);
func (self, &box, user_data);
}
@ -1744,6 +1924,14 @@ add_selection_rectangle_to_path (ClutterText *text,
cogl_path_rectangle (user_data, box->x1, box->y1, box->x2, box->y2);
}
static void
clutter_text_foreach_selection_rectangle_prescaled (ClutterText *self,
ClutterTextSelectionFunc func,
gpointer user_data)
{
clutter_text_foreach_selection_rectangle (self, 1.0f, func, user_data);
}
/* Draws the selected text, its background, and the cursor */
static void
selection_paint (ClutterText *self,
@ -1799,9 +1987,9 @@ selection_paint (ClutterText *self,
else
color = &priv->text_color;
clutter_text_foreach_selection_rectangle (self,
add_selection_rectangle_to_path,
selection_path);
clutter_text_foreach_selection_rectangle_prescaled (self,
add_selection_rectangle_to_path,
selection_path);
cogl_path_fill (selection_path);
@ -1998,7 +2186,8 @@ clutter_text_press (ClutterActor *actor,
return CLUTTER_EVENT_PROPAGATE;
clutter_actor_grab_key_focus (actor);
clutter_input_focus_request_toggle_input_panel (priv->input_focus);
clutter_input_focus_set_input_panel_state (priv->input_focus,
CLUTTER_INPUT_PANEL_STATE_TOGGLE);
/* if the actor is empty we just reset everything and not
* set up the dragging of the selection since there's nothing
@ -2390,6 +2579,7 @@ clutter_text_paint (ClutterActor *self)
guint n_chars;
float alloc_width;
float alloc_height;
float resource_scale;
fb = cogl_get_draw_framebuffer ();
@ -2399,8 +2589,6 @@ clutter_text_paint (ClutterActor *self)
n_chars = clutter_text_buffer_get_length (get_buffer (text));
clutter_actor_get_allocation_box (self, &alloc);
alloc_width = alloc.x2 - alloc.x1;
alloc_height = alloc.y2 - alloc.y1;
if (G_UNLIKELY (default_color_pipeline == NULL))
{
@ -2433,7 +2621,8 @@ clutter_text_paint (ClutterActor *self)
cogl_framebuffer_draw_rectangle (fb,
color_pipeline,
0, 0,
alloc_width, alloc_height);
clutter_actor_box_get_width (&alloc),
clutter_actor_box_get_height (&alloc));
cogl_object_unref (color_pipeline);
}
@ -2446,6 +2635,12 @@ clutter_text_paint (ClutterActor *self)
!clutter_text_should_draw_cursor (text))
return;
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
return;
clutter_actor_box_scale (&alloc, resource_scale);
clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height);
if (priv->editable && priv->single_line_mode)
layout = clutter_text_create_layout (text, -1, -1);
else
@ -2477,8 +2672,15 @@ clutter_text_paint (ClutterActor *self)
}
}
if (resource_scale != 1.0f)
{
float paint_scale = 1.0f / resource_scale;
cogl_framebuffer_push_matrix (fb);
cogl_framebuffer_scale (fb, paint_scale, paint_scale, 1.0f);
}
if (clutter_text_should_draw_cursor (text))
clutter_text_ensure_cursor_position (text);
clutter_text_ensure_cursor_position (text, resource_scale);
if (priv->editable && priv->single_line_mode)
{
@ -2492,7 +2694,7 @@ clutter_text_paint (ClutterActor *self)
clip_set = TRUE;
actor_width = alloc_width - 2 * TEXT_PADDING;
text_width = logical_rect.width / PANGO_SCALE;
text_width = pango_to_pixels (logical_rect.width);
rtl = priv->resolved_direction == PANGO_DIRECTION_RTL;
@ -2549,8 +2751,10 @@ clutter_text_paint (ClutterActor *self)
{
priv->text_x = text_x;
priv->text_y = text_y;
priv->text_logical_x = roundf ((float) text_x / resource_scale);
priv->text_logical_y = roundf ((float) text_y / resource_scale);
clutter_text_ensure_cursor_position (text);
clutter_text_ensure_cursor_position (text, resource_scale);
}
real_opacity = clutter_actor_get_paint_opacity (self)
@ -2569,6 +2773,9 @@ clutter_text_paint (ClutterActor *self)
selection_paint (text, fb);
if (resource_scale != 1.0f)
cogl_framebuffer_pop_matrix (fb);
if (clip_set)
cogl_framebuffer_pop_clip (fb);
}
@ -2598,26 +2805,32 @@ add_selection_to_paint_volume (ClutterText *text,
static void
clutter_text_get_paint_volume_for_cursor (ClutterText *text,
float resource_scale,
ClutterPaintVolume *volume)
{
ClutterTextPrivate *priv = text->priv;
ClutterVertex origin;
clutter_text_ensure_cursor_position (text);
clutter_text_ensure_cursor_position (text, resource_scale);
if (priv->position == priv->selection_bound)
{
origin.x = priv->cursor_rect.origin.x;
origin.y = priv->cursor_rect.origin.y;
float width, height;
width = priv->cursor_rect.size.width / resource_scale;
height = priv->cursor_rect.size.height / resource_scale;
origin.x = priv->cursor_rect.origin.x / resource_scale;
origin.y = priv->cursor_rect.origin.y / resource_scale;
origin.z = 0;
clutter_paint_volume_set_origin (volume, &origin);
clutter_paint_volume_set_width (volume, priv->cursor_rect.size.width);
clutter_paint_volume_set_height (volume, priv->cursor_rect.size.height);
clutter_paint_volume_set_width (volume, width);
clutter_paint_volume_set_height (volume, height);
}
else
{
clutter_text_foreach_selection_rectangle (text,
1.0f / resource_scale,
add_selection_to_paint_volume,
volume);
}
@ -2640,6 +2853,7 @@ clutter_text_get_paint_volume (ClutterActor *self,
PangoLayout *layout;
PangoRectangle ink_rect;
ClutterVertex origin;
float resource_scale;
/* If the text is single line editable then it gets clipped to
the allocation anyway so we can just use that */
@ -2654,19 +2868,24 @@ 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;
_clutter_paint_volume_init_static (&priv->paint_volume, self);
layout = clutter_text_get_layout (text);
pango_layout_get_extents (layout, &ink_rect, NULL);
origin.x = ink_rect.x / (float) PANGO_SCALE;
origin.y = ink_rect.y / (float) PANGO_SCALE;
origin.x = pango_to_logical_pixels (ink_rect.x, resource_scale);
origin.y = pango_to_logical_pixels (ink_rect.y, resource_scale);
origin.z = 0;
clutter_paint_volume_set_origin (&priv->paint_volume, &origin);
clutter_paint_volume_set_width (&priv->paint_volume,
ink_rect.width / (float) PANGO_SCALE);
pango_to_logical_pixels (ink_rect.width,
resource_scale));
clutter_paint_volume_set_height (&priv->paint_volume,
ink_rect.height / (float) PANGO_SCALE);
pango_to_logical_pixels (ink_rect.height,
resource_scale));
/* If the cursor is visible then that will likely be drawn
outside of the ink rectangle so we should merge that in */
@ -2676,7 +2895,8 @@ clutter_text_get_paint_volume (ClutterActor *self,
_clutter_paint_volume_init_static (&cursor_paint_volume, self);
clutter_text_get_paint_volume_for_cursor (text, &cursor_paint_volume);
clutter_text_get_paint_volume_for_cursor (text, resource_scale,
&cursor_paint_volume);
clutter_paint_volume_union (&priv->paint_volume,
&cursor_paint_volume);
@ -2704,9 +2924,12 @@ clutter_text_get_preferred_width (ClutterActor *self,
PangoLayout *layout;
gint logical_width;
gfloat layout_width;
gfloat resource_scale;
if (!clutter_actor_get_resource_scale (self, &resource_scale))
resource_scale = 1;
layout = clutter_text_create_layout (text, -1, -1);
pango_layout_get_extents (layout, NULL, &logical_rect);
/* the X coordinate of the logical rectangle might be non-zero
@ -2716,7 +2939,7 @@ clutter_text_get_preferred_width (ClutterActor *self,
logical_width = logical_rect.x + logical_rect.width;
layout_width = logical_width > 0
? ceilf (logical_width / 1024.0f)
? pango_to_logical_pixels (logical_width, resource_scale)
: 1;
if (min_width_p)
@ -2758,12 +2981,16 @@ clutter_text_get_preferred_height (ClutterActor *self,
PangoRectangle logical_rect = { 0, };
gint logical_height;
gfloat layout_height;
gfloat resource_scale;
if (!clutter_actor_get_resource_scale (self, &resource_scale))
resource_scale = 1;
if (priv->single_line_mode)
for_width = -1;
layout = clutter_text_create_layout (CLUTTER_TEXT (self),
for_width, -1);
layout = create_text_layout_with_scale (CLUTTER_TEXT (self),
for_width, -1, resource_scale);
pango_layout_get_extents (layout, NULL, &logical_rect);
@ -2772,7 +2999,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
* the height accordingly
*/
logical_height = logical_rect.y + logical_rect.height;
layout_height = ceilf (logical_height / 1024.0f);
layout_height = pango_to_logical_pixels (logical_height, resource_scale);
if (min_height_p)
{
@ -2788,7 +3015,8 @@ clutter_text_get_preferred_height (ClutterActor *self,
pango_layout_line_get_extents (line, NULL, &logical_rect);
logical_height = logical_rect.y + logical_rect.height;
line_height = ceilf (logical_height / 1024.0f);
line_height = pango_to_logical_pixels (logical_height,
resource_scale);
*min_height_p = line_height;
}
@ -2819,9 +3047,9 @@ clutter_text_allocate (ClutterActor *self,
if (text->priv->editable && text->priv->single_line_mode)
clutter_text_create_layout (text, -1, -1);
else
clutter_text_create_layout (text,
box->x2 - box->x1,
box->y2 - box->y1);
maybe_create_text_layout_with_resource_scale (text,
box->x2 - box->x1,
box->y2 - box->y1);
parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
parent_class->allocate (self, box, flags);
@ -3547,7 +3775,7 @@ clutter_text_set_final_state (ClutterAnimatable *animatable,
}
static void
clutter_animatable_iface_init (ClutterAnimatableIface *iface)
clutter_animatable_iface_init (ClutterAnimatableInterface *iface)
{
parent_animatable_iface = g_type_interface_peek_parent (iface);
@ -4392,6 +4620,11 @@ 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);
}
/**
@ -5502,6 +5735,7 @@ clutter_text_set_markup (ClutterText *self,
PangoLayout *
clutter_text_get_layout (ClutterText *self)
{
PangoLayout *layout;
gfloat width, height;
g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL);
@ -5510,8 +5744,12 @@ clutter_text_get_layout (ClutterText *self)
return clutter_text_create_layout (self, -1, -1);
clutter_actor_get_size (CLUTTER_ACTOR (self), &width, &height);
layout = maybe_create_text_layout_with_resource_scale (self, width, height);
return clutter_text_create_layout (self, width, height);
if (!layout)
layout = clutter_text_create_layout (self, width, height);
return layout;
}
/**
@ -6515,10 +6753,10 @@ clutter_text_get_layout_offsets (ClutterText *self,
priv = self->priv;
if (x != NULL)
*x = priv->text_x;
*x = priv->text_logical_x;
if (y != NULL)
*y = priv->text_y;
*y = priv->text_logical_y;
}
/**

View File

@ -53,7 +53,8 @@ G_BEGIN_DECLS
*
* Since: 0.4
*/
typedef enum {
typedef enum
{
CLUTTER_TEXTURE_ERROR_OUT_OF_MEMORY,
CLUTTER_TEXTURE_ERROR_NO_YUV,
CLUTTER_TEXTURE_ERROR_BAD_FORMAT

View File

@ -90,7 +90,6 @@ typedef struct _ClutterVertex ClutterVertex;
typedef struct _ClutterAlpha ClutterAlpha;
typedef struct _ClutterAnimation ClutterAnimation;
typedef struct _ClutterAnimator ClutterAnimator;
typedef struct _ClutterState ClutterState;
typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool;
@ -362,6 +361,10 @@ void clutter_rect_inset (ClutterRect *rect
float d_x,
float d_y);
CLUTTER_EXPORT
void clutter_rect_scale (ClutterRect *rect,
float s_x,
float s_y);
CLUTTER_EXPORT
void clutter_rect_clamp_to_pixel (ClutterRect *rect);
CLUTTER_EXPORT
float clutter_rect_get_x (ClutterRect *rect);
@ -561,6 +564,10 @@ void clutter_actor_box_set_size (ClutterActorBox *box,
gfloat width,
gfloat height);
CLUTTER_EXPORT
void clutter_actor_box_scale (ClutterActorBox *box,
gfloat scale);
/**
* ClutterGeometry:
* @x: X coordinate of the top left corner of an actor

View File

@ -39,29 +39,6 @@
#include "clutter-interval.h"
#include "clutter-private.h"
#include "deprecated/clutter-util.h"
/**
* clutter_util_next_p2:
* @a: Value to get the next power
*
* Calculates the nearest power of two, greater than or equal to @a.
*
* Return value: The nearest power of two, greater or equal to @a.
*
* Deprecated: 1.2
*/
gint
clutter_util_next_p2 (gint a)
{
int rval = 1;
while (rval < a)
rval <<= 1;
return rval;
}
/* Help macros to scale from OpenGL <-1,1> coordinates system to
* window coordinates ranging [0,window-size]
*/
@ -128,6 +105,47 @@ _clutter_util_fully_transform_vertices (const CoglMatrix *modelview,
}
}
void _clutter_util_rect_from_rectangle (const cairo_rectangle_int_t *src,
ClutterRect *dest)
{
*dest = (ClutterRect) {
.origin = {
.x = src->x,
.y = src->y
},
.size = {
.width = src->width,
.height = src->height
}
};
}
void _clutter_util_rectangle_int_extents (const ClutterRect *src,
cairo_rectangle_int_t *dest)
{
ClutterRect tmp = *src;
clutter_rect_clamp_to_pixel (&tmp);
*dest = (cairo_rectangle_int_t) {
.x = tmp.origin.x,
.y = tmp.origin.y,
.width = tmp.size.width,
.height = tmp.size.height,
};
}
void _clutter_util_rectangle_offset (const cairo_rectangle_int_t *src,
int x,
int y,
cairo_rectangle_int_t *dest)
{
*dest = *src;
dest->x += x;
dest->y += y;
}
/*< private >
* _clutter_util_rectangle_union:
* @src1: first rectangle to union

View File

@ -76,6 +76,7 @@
#include "clutter-input-focus.h"
#include "clutter-interval.h"
#include "clutter-keyframe-transition.h"
#include "clutter-keymap.h"
#include "clutter-keysyms.h"
#include "clutter-layout-manager.h"
#include "clutter-layout-meta.h"

View File

@ -60,7 +60,8 @@ typedef struct _ClutterStageViewCoglPrivate
G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl,
CLUTTER_TYPE_STAGE_VIEW)
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
static void
clutter_stage_window_iface_init (ClutterStageWindowInterface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
_clutter_stage_cogl,
@ -68,7 +69,8 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init));
enum {
enum
{
PROP_0,
PROP_WRAPPER,
PROP_BACKEND,
@ -549,31 +551,19 @@ calculate_scissor_region (cairo_rectangle_int_t *fb_clip_region,
int fb_height,
cairo_rectangle_int_t *out_scissor_rect)
{
int scissor_x;
int scissor_y;
int scissor_width;
int scissor_height;
*out_scissor_rect = *fb_clip_region;
scissor_x = fb_clip_region->x;
scissor_y = fb_clip_region->y;
scissor_width = fb_clip_region->width;
scissor_height = fb_clip_region->height;
if (subpixel_compensation == 0)
return;
if (fb_clip_region->x > 0)
scissor_x += subpixel_compensation;
out_scissor_rect->x += subpixel_compensation;
if (fb_clip_region->y > 0)
scissor_y += subpixel_compensation;
out_scissor_rect->y += subpixel_compensation;
if (fb_clip_region->x + fb_clip_region->width < fb_width)
scissor_width -= 2 * subpixel_compensation;
out_scissor_rect->width -= 2 * subpixel_compensation;
if (fb_clip_region->y + fb_clip_region->height < fb_height)
scissor_height -= 2 * subpixel_compensation;
*out_scissor_rect = (cairo_rectangle_int_t) {
.x = scissor_x,
.y = scissor_y,
.width = scissor_width,
.height = scissor_height
};
out_scissor_rect->height -= 2 * subpixel_compensation;
}
static inline gboolean
@ -585,6 +575,18 @@ is_buffer_age_enabled (void)
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
}
static void
scale_and_clamp_rect (const ClutterRect *rect,
float scale,
cairo_rectangle_int_t *dest)
{
ClutterRect tmp = *rect;
clutter_rect_scale (&tmp, scale, scale);
_clutter_util_rectangle_int_extents (&tmp, dest);
}
static gboolean
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
ClutterStageView *view)
@ -648,21 +650,22 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
* frames when starting up... */
cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3)
{
ClutterRect rect;
may_use_clipped_redraw = TRUE;
if (fb_scale != floorf (fb_scale))
subpixel_compensation = ceilf (fb_scale);
_clutter_util_rect_from_rectangle (&redraw_clip, &rect);
clutter_rect_offset (&rect, -view_rect.x, -view_rect.y);
scale_and_clamp_rect (&rect, fb_scale, &fb_clip_region);
fb_clip_region = (cairo_rectangle_int_t) {
.x = (floorf ((redraw_clip.x - view_rect.x) * fb_scale) -
subpixel_compensation),
.y = (floorf ((redraw_clip.y - view_rect.y) * fb_scale) -
subpixel_compensation),
.width = (ceilf (redraw_clip.width * fb_scale) +
(2 * subpixel_compensation)),
.height = (ceilf (redraw_clip.height * fb_scale) +
(2 * subpixel_compensation))
};
if (fb_scale != floorf (fb_scale))
{
subpixel_compensation = ceilf (fb_scale);
fb_clip_region.x -= subpixel_compensation;
fb_clip_region.y -= subpixel_compensation;
fb_clip_region.width += 2 * subpixel_compensation;
fb_clip_region.height += 2 * subpixel_compensation;
}
}
else
{
@ -690,6 +693,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
if (valid_buffer_age (view_cogl, age))
{
ClutterRect rect;
cairo_rectangle_int_t damage_region;
*current_fb_damage = fb_clip_region;
@ -705,12 +709,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
/* Update the bounding redraw clip state with the extra damage. */
damage_region = (cairo_rectangle_int_t) {
.x = view_rect.x + floorf (fb_clip_region.x / fb_scale),
.y = view_rect.y + floorf (fb_clip_region.y / fb_scale),
.width = ceilf (fb_clip_region.width / fb_scale),
.height = ceilf (fb_clip_region.height / fb_scale)
};
_clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &damage_region);
_clutter_util_rectangle_offset (&damage_region,
view_rect.x,
view_rect.y,
&damage_region);
_clutter_util_rectangle_union (&stage_cogl->bounding_redraw_clip,
&damage_region,
&stage_cogl->bounding_redraw_clip);
@ -749,7 +753,9 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
else if (use_clipped_redraw)
{
ClutterRect rect;
cairo_rectangle_int_t scissor_rect;
cairo_rectangle_int_t paint_rect;
calculate_scissor_region (&fb_clip_region,
subpixel_compensation,
@ -770,13 +776,15 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
scissor_rect.y,
scissor_rect.width,
scissor_rect.height);
paint_stage (stage_cogl, view,
&(cairo_rectangle_int_t) {
.x = view_rect.x + floorf ((fb_clip_region.x - 0) / fb_scale),
.y = view_rect.y + floorf ((fb_clip_region.y - 0) / fb_scale),
.width = ceilf ((fb_clip_region.width + 0) / fb_scale),
.height = ceilf ((fb_clip_region.height + 0) / fb_scale)
});
_clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
_clutter_util_rectangle_offset (&paint_rect,
view_rect.x,
view_rect.y,
&paint_rect);
paint_stage (stage_cogl, view, &paint_rect);
cogl_framebuffer_pop_clip (fb);
stage_cogl->using_clipped_redraw = FALSE;
@ -791,7 +799,9 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
may_use_clipped_redraw &&
!clip_region_empty)
{
ClutterRect rect;
cairo_rectangle_int_t scissor_rect;
cairo_rectangle_int_t paint_rect;
calculate_scissor_region (&fb_clip_region,
subpixel_compensation,
@ -803,13 +813,15 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
scissor_rect.y,
scissor_rect.width,
scissor_rect.height);
paint_stage (stage_cogl, view,
&(cairo_rectangle_int_t) {
.x = view_rect.x + floorf (fb_clip_region.x / fb_scale),
.y = view_rect.y + floorf (fb_clip_region.y / fb_scale),
.width = ceilf (fb_clip_region.width / fb_scale),
.height = ceilf (fb_clip_region.height / fb_scale)
});
_clutter_util_rect_from_rectangle (&fb_clip_region, &rect);
scale_and_clamp_rect (&rect, 1.0f / fb_scale, &paint_rect);
_clutter_util_rectangle_offset (&paint_rect,
view_rect.x,
view_rect.y,
&paint_rect);
paint_stage (stage_cogl, view, &paint_rect);
cogl_framebuffer_pop_clip (fb);
}
else
@ -994,7 +1006,7 @@ clutter_stage_cogl_get_dirty_pixel (ClutterStageWindow *stage_window,
}
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
{
iface->realize = clutter_stage_cogl_realize;
iface->unrealize = clutter_stage_cogl_unrealize;

View File

@ -7,371 +7,6 @@
#include "clutter-actor-private.h"
#include "clutter-private.h"
#include "clutter-shader.h"
typedef struct _ShaderData ShaderData;
struct _ShaderData
{
ClutterShader *shader;
/* back pointer to the actor */
ClutterActor *actor;
/* list of values that should be set on the shader
* before each paint cycle
*/
GHashTable *value_hash;
};
static void
shader_value_free (gpointer data)
{
GValue *var = data;
g_value_unset (var);
g_slice_free (GValue, var);
}
static void
destroy_shader_data (gpointer data)
{
ShaderData *shader_data = data;
if (shader_data == NULL)
return;
if (shader_data->shader != NULL)
{
g_object_unref (shader_data->shader);
shader_data->shader = NULL;
}
if (shader_data->value_hash != NULL)
{
g_hash_table_destroy (shader_data->value_hash);
shader_data->value_hash = NULL;
}
g_slice_free (ShaderData, shader_data);
}
/**
* clutter_actor_get_shader:
* @self: a #ClutterActor
*
* Queries the currently set #ClutterShader on @self.
*
* Return value: (transfer none): The currently set #ClutterShader
* or %NULL if no shader is set.
*
* Since: 0.6
*
* Deprecated: 1.8: Use clutter_actor_get_effect() instead.
*/
ClutterShader *
clutter_actor_get_shader (ClutterActor *self)
{
ShaderData *shader_data;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL);
shader_data = g_object_get_data (G_OBJECT (self), "-clutter-actor-shader-data");
if (shader_data != NULL)
return shader_data->shader;
return NULL;
}
/**
* clutter_actor_set_shader:
* @self: a #ClutterActor
* @shader: (allow-none): a #ClutterShader or %NULL to unset the shader.
*
* Sets the #ClutterShader to be used when rendering @self.
*
* If @shader is %NULL this function will unset any currently set shader
* for the actor.
*
* Any #ClutterEffect applied to @self will take the precedence
* over the #ClutterShader set using this function.
*
* Return value: %TRUE if the shader was successfully applied
* or removed
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect and
* clutter_actor_add_effect() instead.
*/
gboolean
clutter_actor_set_shader (ClutterActor *self,
ClutterShader *shader)
{
ShaderData *shader_data;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
g_return_val_if_fail (shader == NULL || CLUTTER_IS_SHADER (shader), FALSE);
if (shader != NULL)
g_object_ref (shader);
else
{
/* if shader passed in is NULL we destroy the shader */
g_object_set_data (G_OBJECT (self), "-clutter-actor-shader-data", NULL);
return TRUE;
}
shader_data = g_object_get_data (G_OBJECT (self), "-clutter-actor-shader-data");
if (shader_data == NULL)
{
shader_data = g_slice_new (ShaderData);
shader_data->actor = self;
shader_data->shader = NULL;
shader_data->value_hash =
g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
shader_value_free);
g_object_set_data_full (G_OBJECT (self), "-clutter-actor-shader-data",
shader_data,
destroy_shader_data);
}
if (shader_data->shader != NULL)
g_object_unref (shader_data->shader);
shader_data->shader = shader;
clutter_actor_queue_redraw (self);
return TRUE;
}
static void
set_each_param (gpointer key,
gpointer value,
gpointer user_data)
{
ClutterShader *shader = user_data;
const gchar *uniform = key;
GValue *var = value;
clutter_shader_set_uniform (shader, uniform, var);
}
void
_clutter_actor_shader_pre_paint (ClutterActor *actor,
gboolean repeat)
{
ShaderData *shader_data;
ClutterShader *shader;
shader_data = g_object_get_data (G_OBJECT (actor), "-clutter-actor-shader-data");
if (shader_data == NULL)
return;
shader = shader_data->shader;
if (shader != NULL)
{
clutter_shader_set_is_enabled (shader, TRUE);
g_hash_table_foreach (shader_data->value_hash, set_each_param, shader);
if (!repeat)
_clutter_context_push_shader_stack (actor);
}
}
void
_clutter_actor_shader_post_paint (ClutterActor *actor)
{
ShaderData *shader_data;
ClutterShader *shader;
shader_data = g_object_get_data (G_OBJECT (actor), "-clutter-actor-shader-data");
if (G_LIKELY (shader_data == NULL))
return;
shader = shader_data->shader;
if (shader != NULL)
{
ClutterActor *head;
clutter_shader_set_is_enabled (shader, FALSE);
/* remove the actor from the shaders stack; if there is another
* actor inside it, then call pre-paint again to set its shader
* but this time with the second argument being TRUE, indicating
* that we are re-applying an existing shader and thus should it
* not be prepended to the stack
*/
head = _clutter_context_pop_shader_stack (actor);
if (head != NULL)
_clutter_actor_shader_pre_paint (head, TRUE);
}
}
static inline void
clutter_actor_set_shader_param_internal (ClutterActor *self,
const gchar *param,
const GValue *value)
{
ShaderData *shader_data;
GValue *var;
shader_data = g_object_get_data (G_OBJECT (self), "-clutter-actor-shader-data");
if (shader_data == NULL)
return;
var = g_slice_new0 (GValue);
g_value_init (var, G_VALUE_TYPE (value));
g_value_copy (value, var);
g_hash_table_insert (shader_data->value_hash, g_strdup (param), var);
clutter_actor_queue_redraw (self);
}
/**
* clutter_actor_set_shader_param:
* @self: a #ClutterActor
* @param: the name of the parameter
* @value: the value of the parameter
*
* Sets the value for a named parameter of the shader applied
* to @actor.
*
* Since: 1.0
*
* Deprecated: 1.8: Use clutter_shader_effect_set_uniform_value() instead
*/
void
clutter_actor_set_shader_param (ClutterActor *self,
const gchar *param,
const GValue *value)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (param != NULL);
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_INT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value) ||
G_VALUE_HOLDS_FLOAT (value) ||
G_VALUE_HOLDS_INT (value));
clutter_actor_set_shader_param_internal (self, param, value);
}
/**
* clutter_actor_set_shader_param_float:
* @self: a #ClutterActor
* @param: the name of the parameter
* @value: the value of the parameter
*
* Sets the value for a named float parameter of the shader applied
* to @actor.
*
* Since: 0.8
*
* Deprecated: 1.8: Use clutter_shader_effect_set_uniform() instead
*/
void
clutter_actor_set_shader_param_float (ClutterActor *self,
const gchar *param,
gfloat value)
{
GValue var = { 0, };
g_value_init (&var, G_TYPE_FLOAT);
g_value_set_float (&var, value);
clutter_actor_set_shader_param_internal (self, param, &var);
g_value_unset (&var);
}
/**
* clutter_actor_set_shader_param_int:
* @self: a #ClutterActor
* @param: the name of the parameter
* @value: the value of the parameter
*
* Sets the value for a named int parameter of the shader applied to
* @actor.
*
* Since: 0.8
*
* Deprecated: 1.8: Use clutter_shader_effect_set_uniform() instead
*/
void
clutter_actor_set_shader_param_int (ClutterActor *self,
const gchar *param,
gint value)
{
GValue var = { 0, };
g_value_init (&var, G_TYPE_INT);
g_value_set_int (&var, value);
clutter_actor_set_shader_param_internal (self, param, &var);
g_value_unset (&var);
}
/**
* clutter_actor_set_geometry:
* @self: A #ClutterActor
* @geometry: A #ClutterGeometry
*
* Sets the actor's fixed position and forces its minimum and natural
* size, in pixels. This means the untransformed actor will have the
* given geometry. This is the same as calling clutter_actor_set_position()
* and clutter_actor_set_size().
*
* Deprecated: 1.10: Use clutter_actor_set_position() and
* clutter_actor_set_size() instead.
*/
void
clutter_actor_set_geometry (ClutterActor *self,
const ClutterGeometry *geometry)
{
g_object_freeze_notify (G_OBJECT (self));
clutter_actor_set_position (self, geometry->x, geometry->y);
clutter_actor_set_size (self, geometry->width, geometry->height);
g_object_thaw_notify (G_OBJECT (self));
}
/**
* clutter_actor_get_geometry:
* @self: A #ClutterActor
* @geometry: (out caller-allocates): A location to store actors #ClutterGeometry
*
* Gets the size and position of an actor relative to its parent
* actor. This is the same as calling clutter_actor_get_position() and
* clutter_actor_get_size(). It tries to "do what you mean" and get the
* requested size and position if the actor's allocation is invalid.
*
* Deprecated: 1.10: Use clutter_actor_get_position() and
* clutter_actor_get_size(), or clutter_actor_get_allocation_geometry()
* instead.
*/
void
clutter_actor_get_geometry (ClutterActor *self,
ClutterGeometry *geometry)
{
gfloat x, y, width, height;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (geometry != NULL);
clutter_actor_get_position (self, &x, &y);
clutter_actor_get_size (self, &width, &height);
geometry->x = (int) x;
geometry->y = (int) y;
geometry->width = (int) width;
geometry->height = (int) height;
}
/**
* clutter_actor_get_allocation_geometry:

View File

@ -33,13 +33,6 @@
G_BEGIN_DECLS
CLUTTER_DEPRECATED
void clutter_actor_set_geometry (ClutterActor *self,
const ClutterGeometry *geometry);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_allocation_geometry)
void clutter_actor_get_geometry (ClutterActor *self,
ClutterGeometry *geometry);
CLUTTER_DEPRECATED
guint32 clutter_actor_get_gid (ClutterActor *self);

File diff suppressed because it is too large Load Diff

View File

@ -1,188 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2010 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Øyvind Kolås <pippin@linux.intel.com>
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_ANIMATOR_H__
#define __CLUTTER_ANIMATOR_H__
#include <clutter/clutter-types.h>
#include <clutter/clutter-timeline.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_ANIMATOR (clutter_animator_get_type ())
#define CLUTTER_TYPE_ANIMATOR_KEY (clutter_animator_key_get_type ())
#define CLUTTER_ANIMATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATOR, ClutterAnimator))
#define CLUTTER_ANIMATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ANIMATOR, ClutterAnimatorClass))
#define CLUTTER_IS_ANIMATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATOR))
#define CLUTTER_IS_ANIMATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ANIMATOR))
#define CLUTTER_ANIMATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ANIMATOR, ClutterAnimatorClass))
/* ClutterAnimator is typedef in clutter-types.h */
typedef struct _ClutterAnimatorClass ClutterAnimatorClass;
typedef struct _ClutterAnimatorPrivate ClutterAnimatorPrivate;
/**
* ClutterAnimatorKey:
*
* A key frame inside a #ClutterAnimator
*
* Since: 1.2
*
* Deprecated: 1.12
*/
typedef struct _ClutterAnimatorKey ClutterAnimatorKey;
/**
* ClutterAnimator:
*
* The #ClutterAnimator structure contains only private data and
* should be accessed using the provided API
*
* Since: 1.2
*
* Deprecated: 1.12
*/
struct _ClutterAnimator
{
/*< private >*/
GObject parent_instance;
ClutterAnimatorPrivate *priv;
};
/**
* ClutterAnimatorClass:
*
* The #ClutterAnimatorClass structure contains only private data
*
* Since: 1.2
*
* Deprecated: 1.12
*/
struct _ClutterAnimatorClass
{
/*< private >*/
GObjectClass parent_class;
/* padding for future expansion */
gpointer _padding_dummy[16];
};
CLUTTER_DEPRECATED
GType clutter_animator_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
ClutterAnimator * clutter_animator_new (void);
CLUTTER_DEPRECATED
ClutterAnimator * clutter_animator_set_key (ClutterAnimator *animator,
GObject *object,
const gchar *property_name,
guint mode,
gdouble progress,
const GValue *value);
CLUTTER_DEPRECATED
void clutter_animator_set (ClutterAnimator *animator,
gpointer first_object,
const gchar *first_property_name,
guint first_mode,
gdouble first_progress,
...) G_GNUC_NULL_TERMINATED;
CLUTTER_DEPRECATED
GList * clutter_animator_get_keys (ClutterAnimator *animator,
GObject *object,
const gchar *property_name,
gdouble progress);
CLUTTER_DEPRECATED
void clutter_animator_remove_key (ClutterAnimator *animator,
GObject *object,
const gchar *property_name,
gdouble progress);
CLUTTER_DEPRECATED
ClutterTimeline * clutter_animator_start (ClutterAnimator *animator);
CLUTTER_DEPRECATED
gboolean clutter_animator_compute_value (ClutterAnimator *animator,
GObject *object,
const gchar *property_name,
gdouble progress,
GValue *value);
CLUTTER_DEPRECATED
ClutterTimeline * clutter_animator_get_timeline (ClutterAnimator *animator);
CLUTTER_DEPRECATED
void clutter_animator_set_timeline (ClutterAnimator *animator,
ClutterTimeline *timeline);
CLUTTER_DEPRECATED
guint clutter_animator_get_duration (ClutterAnimator *animator);
CLUTTER_DEPRECATED
void clutter_animator_set_duration (ClutterAnimator *animator,
guint duration);
CLUTTER_DEPRECATED
gboolean clutter_animator_property_get_ease_in (ClutterAnimator *animator,
GObject *object,
const gchar *property_name);
CLUTTER_DEPRECATED
void clutter_animator_property_set_ease_in (ClutterAnimator *animator,
GObject *object,
const gchar *property_name,
gboolean ease_in);
CLUTTER_DEPRECATED
ClutterInterpolation clutter_animator_property_get_interpolation (ClutterAnimator *animator,
GObject *object,
const gchar *property_name);
CLUTTER_DEPRECATED
void clutter_animator_property_set_interpolation (ClutterAnimator *animator,
GObject *object,
const gchar *property_name,
ClutterInterpolation interpolation);
CLUTTER_DEPRECATED
GType clutter_animator_key_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
GObject * clutter_animator_key_get_object (const ClutterAnimatorKey *key);
CLUTTER_DEPRECATED
const gchar * clutter_animator_key_get_property_name (const ClutterAnimatorKey *key);
CLUTTER_DEPRECATED
GType clutter_animator_key_get_property_type (const ClutterAnimatorKey *key);
CLUTTER_DEPRECATED
gulong clutter_animator_key_get_mode (const ClutterAnimatorKey *key);
CLUTTER_DEPRECATED
gdouble clutter_animator_key_get_progress (const ClutterAnimatorKey *key);
CLUTTER_DEPRECATED
gboolean clutter_animator_key_get_value (const ClutterAnimatorKey *key,
GValue *value);
G_END_DECLS
#endif /* __CLUTTER_ANIMATOR_H__ */

View File

@ -1,64 +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_BACKEND_DEPRECATED_H__
#define __CLUTTER_BACKEND_DEPRECATED_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
CLUTTER_DEPRECATED_FOR(ClutterSettings:font_dpi)
void clutter_backend_set_resolution (ClutterBackend *backend,
gdouble dpi);
CLUTTER_DEPRECATED_FOR(ClutterSettings:double_click_time)
void clutter_backend_set_double_click_time (ClutterBackend *backend,
guint msec);
CLUTTER_DEPRECATED_FOR(ClutterSettings:double_click_time)
guint clutter_backend_get_double_click_time (ClutterBackend *backend);
CLUTTER_DEPRECATED_FOR(ClutterSettings:double_click_distance)
void clutter_backend_set_double_click_distance (ClutterBackend *backend,
guint distance);
CLUTTER_DEPRECATED_FOR(ClutterSettings:double_click_distance)
guint clutter_backend_get_double_click_distance (ClutterBackend *backend);
CLUTTER_DEPRECATED_FOR(ClutterSettings:font_name)
void clutter_backend_set_font_name (ClutterBackend *backend,
const gchar *font_name);
CLUTTER_DEPRECATED_FOR(ClutterSettings:font_name)
const gchar * clutter_backend_get_font_name (ClutterBackend *backend);
G_END_DECLS
#endif /* __CLUTTER_BACKEND_DEPRECATED_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Tomas Frydrych <tf@openedhand.com>
*
* Copyright (C) 2007 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_BEHAVIOUR_ELLIPSE_H__
#define __CLUTTER_BEHAVIOUR_ELLIPSE_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR_ELLIPSE (clutter_behaviour_ellipse_get_type ())
#define CLUTTER_BEHAVIOUR_ELLIPSE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, ClutterBehaviourEllipse))
#define CLUTTER_BEHAVIOUR_ELLIPSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, ClutterBehaviourEllipseClass))
#define CLUTTER_IS_BEHAVIOUR_ELLIPSE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
CLUTTER_TYPE_BEHAVIOUR_ELLIPSE))
#define CLUTTER_IS_BEHAVIOUR_ELLIPSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_BEHAVIOUR_ELLIPSE))
#define CLUTTER_BEHAVIOUR_ELLIPSE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_BEHAVIOUR_ELLIPSE, ClutterBehaviourEllipseClass))
typedef struct _ClutterBehaviourEllipse ClutterBehaviourEllipse;
typedef struct _ClutterBehaviourEllipsePrivate ClutterBehaviourEllipsePrivate;
typedef struct _ClutterBehaviourEllipseClass ClutterBehaviourEllipseClass;
/**
* ClutterBehaviourEllipse:
*
* The #ClutterBehaviourEllipse struct contains only private data
* and should be accessed using the provided API
*
* Since: 0.4
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourEllipse
{
/*< private >*/
ClutterBehaviour parent_instance;
ClutterBehaviourEllipsePrivate *priv;
};
/**
* ClutterBehaviourEllipseClass:
*
* The #ClutterBehaviourEllipseClass struct contains only private data
*
* Since: 0.4
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourEllipseClass
{
/*< private >*/
ClutterBehaviourClass parent_class;
};
CLUTTER_DEPRECATED
GType clutter_behaviour_ellipse_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_animate)
ClutterBehaviour * clutter_behaviour_ellipse_new (ClutterAlpha *alpha,
gint x,
gint y,
gint width,
gint height,
ClutterRotateDirection direction,
gdouble start,
gdouble end);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_center (ClutterBehaviourEllipse *self,
gint x,
gint y);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_get_center (ClutterBehaviourEllipse *self,
gint *x,
gint *y);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_width (ClutterBehaviourEllipse *self,
gint width);
CLUTTER_DEPRECATED
gint clutter_behaviour_ellipse_get_width (ClutterBehaviourEllipse *self);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_height (ClutterBehaviourEllipse *self,
gint height);
CLUTTER_DEPRECATED
gint clutter_behaviour_ellipse_get_height (ClutterBehaviourEllipse *self);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_angle_start (ClutterBehaviourEllipse *self,
gdouble angle_start);
CLUTTER_DEPRECATED
gdouble clutter_behaviour_ellipse_get_angle_start (ClutterBehaviourEllipse *self);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_angle_end (ClutterBehaviourEllipse *self,
gdouble angle_end);
CLUTTER_DEPRECATED
gdouble clutter_behaviour_ellipse_get_angle_end (ClutterBehaviourEllipse *self);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_angle_tilt (ClutterBehaviourEllipse *self,
ClutterRotateAxis axis,
gdouble angle_tilt);
CLUTTER_DEPRECATED
gdouble clutter_behaviour_ellipse_get_angle_tilt (ClutterBehaviourEllipse *self,
ClutterRotateAxis axis);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_tilt (ClutterBehaviourEllipse *self,
gdouble angle_tilt_x,
gdouble angle_tilt_y,
gdouble angle_tilt_z);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_get_tilt (ClutterBehaviourEllipse *self,
gdouble *angle_tilt_x,
gdouble *angle_tilt_y,
gdouble *angle_tilt_z);
CLUTTER_DEPRECATED
ClutterRotateDirection clutter_behaviour_ellipse_get_direction (ClutterBehaviourEllipse *self);
CLUTTER_DEPRECATED
void clutter_behaviour_ellipse_set_direction (ClutterBehaviourEllipse *self,
ClutterRotateDirection direction);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_ELLIPSE_H__ */

View File

@ -1,465 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By:
* Matthew Allum <mallum@openedhand.com>
* Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
* Copyright (C) 2009, 2010 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:clutter-behaviour-path
* @Title: ClutterBehaviourPath
* @short_description: A behaviour for moving actors along a #ClutterPath
* @Deprecated: 1.6: Use #ClutterPathConstraint and clutter_actor_animate()
* with the #ClutterPathConstraint:offset property instead.
*
* #ClutterBehaviourPath interpolates actors along a defined path.
*
* A path is described by a #ClutterPath object. The path can contain
* straight line parts and bezier curves. If the path contains
* %CLUTTER_PATH_MOVE_TO parts then the actors will jump to those
* coordinates. This can be used make disjoint paths.
*
* When creating a path behaviour in a #ClutterScript, you can specify
* the path property directly as a string. For example:
*
* |[
* {
* "id" : "spline-path",
* "type" : "ClutterBehaviourPath",
* "path" : "M 50 50 L 100 100",
* "alpha" : {
* "timeline" : "main-timeline",
* "function" : "ramp
* }
* }
* ]|
*
* If the alpha function is a periodic function, i.e. it returns to
* 0.0 after reaching 1.0, then the actors will walk the path back to the
* starting #ClutterKnot.
*
* #ClutterBehaviourPath is available since Clutter 0.2
*
* Deprecated: 1.6: Use #ClutterPath and #ClutterPathConstraint with
* clutter_actor_animate() instead.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-alpha.h"
#include "clutter-behaviour.h"
#include "clutter-behaviour-path.h"
#include "clutter-bezier.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-script-private.h"
#include "clutter-scriptable.h"
#include <math.h>
struct _ClutterBehaviourPathPrivate
{
ClutterPath *path;
guint last_knot_passed;
};
enum
{
KNOT_REACHED,
LAST_SIGNAL
};
static guint path_signals[LAST_SIGNAL] = { 0, };
enum
{
PROP_0,
PROP_PATH,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterBehaviourPath,
clutter_behaviour_path,
CLUTTER_TYPE_BEHAVIOUR,
G_ADD_PRIVATE (ClutterBehaviourPath)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
clutter_scriptable_iface_init))
static void
actor_apply_knot_foreach (ClutterBehaviour *behaviour,
ClutterActor *actor,
gpointer data)
{
ClutterKnot *knot = data;
CLUTTER_NOTE (ANIMATION, "Setting actor to %ix%i", knot->x, knot->y);
clutter_actor_set_position (actor, knot->x, knot->y);
}
static void
clutter_behaviour_path_alpha_notify (ClutterBehaviour *behave,
gdouble alpha_value)
{
ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (behave);
ClutterBehaviourPathPrivate *priv = pathb->priv;
ClutterKnot position;
guint knot_num;
if (priv->path)
knot_num = clutter_path_get_position (priv->path, alpha_value, &position);
else
{
memset (&position, 0, sizeof (position));
knot_num = 0;
}
clutter_behaviour_actors_foreach (behave,
actor_apply_knot_foreach,
&position);
if (knot_num != priv->last_knot_passed)
{
g_signal_emit (behave, path_signals[KNOT_REACHED], 0, knot_num);
priv->last_knot_passed = knot_num;
}
}
static void
clutter_behaviour_path_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (gobject);
switch (prop_id)
{
case PROP_PATH:
g_value_set_object (value, clutter_behaviour_path_get_path (pathb));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_path_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (gobject);
switch (prop_id)
{
case PROP_PATH:
clutter_behaviour_path_set_path (pathb, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_path_dispose (GObject *gobject)
{
ClutterBehaviourPath *pathb = CLUTTER_BEHAVIOUR_PATH (gobject);
clutter_behaviour_path_set_path (pathb, NULL);
G_OBJECT_CLASS (clutter_behaviour_path_parent_class)->dispose (gobject);
}
static void
clutter_behaviour_path_class_init (ClutterBehaviourPathClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBehaviourClass *behave_class = CLUTTER_BEHAVIOUR_CLASS (klass);
GParamSpec *pspec;
gobject_class->get_property = clutter_behaviour_path_get_property;
gobject_class->set_property = clutter_behaviour_path_set_property;
gobject_class->dispose = clutter_behaviour_path_dispose;
pspec = g_param_spec_object ("path",
P_("Path"),
P_("The ClutterPath object representing the path "
"to animate along"),
CLUTTER_TYPE_PATH,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_PATH] = pspec;
g_object_class_install_property (gobject_class, PROP_PATH, pspec);
/**
* ClutterBehaviourPath::knot-reached:
* @pathb: the object which received the signal
* @knot_num: the index of the #ClutterKnot reached
*
* This signal is emitted each time a node defined inside the path
* is reached.
*
* Since: 0.2
*
* Deprecated: 1.6
*/
path_signals[KNOT_REACHED] =
g_signal_new ("knot-reached",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ClutterBehaviourPathClass, knot_reached),
NULL, NULL,
_clutter_marshal_VOID__UINT,
G_TYPE_NONE, 1,
G_TYPE_UINT);
behave_class->alpha_notify = clutter_behaviour_path_alpha_notify;
}
static ClutterScriptableIface *parent_scriptable_iface = NULL;
static gboolean
clutter_behaviour_path_parse_custom_node (ClutterScriptable *scriptable,
ClutterScript *script,
GValue *value,
const gchar *name,
JsonNode *node)
{
if (strcmp ("path", name) == 0)
{
ClutterPath *path;
GValue node_value = { 0 };
path = g_object_ref_sink (clutter_path_new ());
json_node_get_value (node, &node_value);
if (!G_VALUE_HOLDS (&node_value, G_TYPE_STRING)
|| !clutter_path_set_description (path,
g_value_get_string (&node_value)))
g_warning ("Invalid path description");
g_value_unset (&node_value);
g_value_init (value, G_TYPE_OBJECT);
g_value_take_object (value, path);
return TRUE;
}
/* chain up */
else if (parent_scriptable_iface->parse_custom_node)
return parent_scriptable_iface->parse_custom_node (scriptable, script,
value, name, node);
else
return FALSE;
}
static void
clutter_scriptable_iface_init (ClutterScriptableIface *iface)
{
parent_scriptable_iface = g_type_interface_peek_parent (iface);
if (!parent_scriptable_iface)
parent_scriptable_iface
= g_type_default_interface_peek (CLUTTER_TYPE_SCRIPTABLE);
iface->parse_custom_node = clutter_behaviour_path_parse_custom_node;
}
static void
clutter_behaviour_path_init (ClutterBehaviourPath *self)
{
self->priv = clutter_behaviour_path_get_instance_private (self);
self->priv->last_knot_passed = G_MAXUINT;
}
/**
* clutter_behaviour_path_new:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @path: a #ClutterPath or %NULL for an empty path
*
* Creates a new path behaviour. You can use this behaviour to drive
* actors along the nodes of a path, described by @path.
*
* This will claim the floating reference on the #ClutterPath so you
* do not need to unref if it.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: (transfer full): a #ClutterBehaviour
*
* Since: 0.2
*
* Deprecated: 1.6
*/
ClutterBehaviour *
clutter_behaviour_path_new (ClutterAlpha *alpha,
ClutterPath *path)
{
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_PATH,
"alpha", alpha,
"path", path,
NULL);
}
/**
* clutter_behaviour_path_new_with_description:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @desc: a string description of the path
*
* Creates a new path behaviour using the path described by @desc. See
* clutter_path_add_string() for a description of the format.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: (transfer full): a #ClutterBehaviour
*
* Since: 1.0
*
* Deprecated: 1.6
*/
ClutterBehaviour *
clutter_behaviour_path_new_with_description (ClutterAlpha *alpha,
const gchar *desc)
{
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_PATH,
"alpha", alpha,
"path", clutter_path_new_with_description (desc),
NULL);
}
/**
* clutter_behaviour_path_new_with_knots:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @knots: (array length=n_knots): an array of #ClutterKnot<!-- -->s
* @n_knots: number of entries in @knots
*
* Creates a new path behaviour that will make the actors visit all of
* the given knots in order with straight lines in between.
*
* A path will be created where the first knot is used in a
* %CLUTTER_PATH_MOVE_TO and the subsequent knots are used in
* %CLUTTER_PATH_LINE_TO<!-- -->s.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: (transfer full): a #ClutterBehaviour
*
* Since: 1.0
*
* Deprecated: 1.6
*/
ClutterBehaviour *
clutter_behaviour_path_new_with_knots (ClutterAlpha *alpha,
const ClutterKnot *knots,
guint n_knots)
{
ClutterPath *path = clutter_path_new ();
guint i;
if (n_knots > 0)
{
clutter_path_add_move_to (path, knots[0].x, knots[0].y);
for (i = 1; i < n_knots; i++)
clutter_path_add_line_to (path, knots[i].x, knots[i].y);
}
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_PATH,
"alpha", alpha,
"path", path,
NULL);
}
/**
* clutter_behaviour_path_set_path:
* @pathb: the path behaviour
* @path: the new path to follow
*
* Change the path that the actors will follow. This will take the
* floating reference on the #ClutterPath so you do not need to unref
* it.
*
* Since: 1.0
*
* Deprecated: 1.6
*/
void
clutter_behaviour_path_set_path (ClutterBehaviourPath *pathb,
ClutterPath *path)
{
ClutterBehaviourPathPrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_PATH (pathb));
priv = pathb->priv;
if (path)
g_object_ref_sink (path);
if (priv->path)
g_object_unref (priv->path);
priv->path = path;
g_object_notify_by_pspec (G_OBJECT (pathb), obj_props[PROP_PATH]);
}
/**
* clutter_behaviour_path_get_path:
* @pathb: a #ClutterBehaviourPath instance
*
* Get the current path of the behaviour
*
* Return value: (transfer none): the path
*
* Since: 1.0
*
* Deprecated: 1.6
*/
ClutterPath *
clutter_behaviour_path_get_path (ClutterBehaviourPath *pathb)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_PATH (pathb), NULL);
return pathb->priv->path;
}

View File

@ -1,135 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@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_BEHAVIOUR_PATH_H__
#define __CLUTTER_BEHAVIOUR_PATH_H__
#include <clutter/clutter-types.h>
#include <clutter/clutter-path.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR_PATH (clutter_behaviour_path_get_type ())
#define CLUTTER_BEHAVIOUR_PATH(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
CLUTTER_TYPE_BEHAVIOUR_PATH, ClutterBehaviourPath))
#define CLUTTER_BEHAVIOUR_PATH_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
CLUTTER_TYPE_BEHAVIOUR_PATH, ClutterBehaviourPathClass))
#define CLUTTER_IS_BEHAVIOUR_PATH(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
CLUTTER_TYPE_BEHAVIOUR_PATH))
#define CLUTTER_IS_BEHAVIOUR_PATH_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_BEHAVIOUR_PATH))
#define CLUTTER_BEHAVIOUR_PATH_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_BEHAVIOUR_PATH, ClutterBehaviourPathClass))
typedef struct _ClutterBehaviourPath ClutterBehaviourPath;
typedef struct _ClutterBehaviourPathPrivate ClutterBehaviourPathPrivate;
typedef struct _ClutterBehaviourPathClass ClutterBehaviourPathClass;
/**
* ClutterBehaviourPath:
*
* The #ClutterBehaviourPath structure contains only private data
* and should be accessed using the provided API
*
* Since: 0.2
*
* Deprecated: 1.6: Use #ClutterPathConstraint and clutter_actor_animate()
* instead.
*/
struct _ClutterBehaviourPath
{
/*< private >*/
ClutterBehaviour parent;
ClutterBehaviourPathPrivate *priv;
};
/**
* ClutterBehaviourPathClass:
* @knot_reached: signal class handler for the
* ClutterBehaviourPath::knot_reached signal
*
* The #ClutterBehaviourPathClass struct contains only private data
*
* Since: 0.2
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourPathClass
{
/*< private >*/
ClutterBehaviourClass parent_class;
/*< public >*/
void (*knot_reached) (ClutterBehaviourPath *pathb,
guint knot_num);
/*< private >*/
void (*_clutter_path_1) (void);
void (*_clutter_path_2) (void);
void (*_clutter_path_3) (void);
void (*_clutter_path_4) (void);
};
CLUTTER_DEPRECATED
GType clutter_behaviour_path_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_animate)
ClutterBehaviour *clutter_behaviour_path_new (ClutterAlpha *alpha,
ClutterPath *path);
CLUTTER_DEPRECATED_FOR(clutter_actor_animate)
ClutterBehaviour *clutter_behaviour_path_new_with_description
(ClutterAlpha *alpha,
const gchar *desc);
CLUTTER_DEPRECATED_FOR(clutter_actor_animate)
ClutterBehaviour *clutter_behaviour_path_new_with_knots
(ClutterAlpha *alpha,
const ClutterKnot *knots,
guint n_knots);
CLUTTER_DEPRECATED
void clutter_behaviour_path_set_path (ClutterBehaviourPath *pathb,
ClutterPath *path);
CLUTTER_DEPRECATED
ClutterPath * clutter_behaviour_path_get_path (ClutterBehaviourPath *pathb);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_PATH_H__ */

View File

@ -1,688 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2007 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-behaviour-rotate
* @short_description: A behaviour controlling rotation
*
* A #ClutterBehaviourRotate rotate actors between a starting and ending
* angle on a given axis.
*
* The #ClutterBehaviourRotate is available since version 0.4.
*
* Deprecated: 1.6: Use the #ClutterActor rotation properties and
* clutter_actor_animate(), or #ClutterAnimator, or #ClutterState
* instead.
*/
#include "clutter-build-config.h"
#include <math.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-actor.h"
#include "clutter-alpha.h"
#include "clutter-behaviour.h"
#include "clutter-behaviour-rotate.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-main.h"
#include "clutter-private.h"
struct _ClutterBehaviourRotatePrivate
{
gdouble angle_start;
gdouble angle_end;
ClutterRotateAxis axis;
ClutterRotateDirection direction;
gint center_x;
gint center_y;
gint center_z;
};
enum
{
PROP_0,
PROP_ANGLE_START,
PROP_ANGLE_END,
PROP_AXIS,
PROP_DIRECTION,
PROP_CENTER_X,
PROP_CENTER_Y,
PROP_CENTER_Z,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBehaviourRotate,
clutter_behaviour_rotate,
CLUTTER_TYPE_BEHAVIOUR)
typedef struct {
gdouble angle;
} RotateFrameClosure;
static void
alpha_notify_foreach (ClutterBehaviour *behaviour,
ClutterActor *actor,
gpointer data)
{
RotateFrameClosure *closure = data;
ClutterBehaviourRotate *rotate_behaviour;
ClutterBehaviourRotatePrivate *priv;
rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour);
priv = rotate_behaviour->priv;
clutter_actor_set_rotation (actor, priv->axis,
closure->angle,
priv->center_x,
priv->center_y,
priv->center_z);
}
static inline float
clamp_angle (float a)
{
float a1, a2;
gint rounds;
rounds = a / 360.0;
a1 = rounds * 360.0;
a2 = a - a1;
return a2;
}
static void
clutter_behaviour_rotate_alpha_notify (ClutterBehaviour *behaviour,
gdouble alpha_value)
{
ClutterBehaviourRotate *rotate_behaviour;
ClutterBehaviourRotatePrivate *priv;
RotateFrameClosure closure;
gdouble start, end;
rotate_behaviour = CLUTTER_BEHAVIOUR_ROTATE (behaviour);
priv = rotate_behaviour->priv;
closure.angle = 0;
start = priv->angle_start;
end = priv->angle_end;
if (priv->direction == CLUTTER_ROTATE_CW && start >= end)
end += 360.0;
else if (priv->direction == CLUTTER_ROTATE_CCW && start <= end)
end -= 360.0;
closure.angle = (end - start) * alpha_value + start;
clutter_behaviour_actors_foreach (behaviour,
alpha_notify_foreach,
&closure);
}
static void
clutter_behaviour_rotate_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourRotate *rotate;
ClutterBehaviourRotatePrivate *priv;
rotate = CLUTTER_BEHAVIOUR_ROTATE (gobject);
priv = rotate->priv;
switch (prop_id)
{
case PROP_ANGLE_START:
priv->angle_start = g_value_get_double (value);
break;
case PROP_ANGLE_END:
priv->angle_end = g_value_get_double (value);
break;
case PROP_AXIS:
priv->axis = g_value_get_enum (value);
break;
case PROP_DIRECTION:
priv->direction = g_value_get_enum (value);
break;
case PROP_CENTER_X:
clutter_behaviour_rotate_set_center (rotate,
g_value_get_int (value),
priv->center_y,
priv->center_z);
break;
case PROP_CENTER_Y:
clutter_behaviour_rotate_set_center (rotate,
priv->center_x,
g_value_get_int (value),
priv->center_z);
break;
case PROP_CENTER_Z:
clutter_behaviour_rotate_set_center (rotate,
priv->center_x,
priv->center_y,
g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_rotate_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterBehaviourRotatePrivate *priv;
priv = CLUTTER_BEHAVIOUR_ROTATE (gobject)->priv;
switch (prop_id)
{
case PROP_ANGLE_START:
g_value_set_double (value, priv->angle_start);
break;
case PROP_ANGLE_END:
g_value_set_double (value, priv->angle_end);
break;
case PROP_AXIS:
g_value_set_enum (value, priv->axis);
break;
case PROP_DIRECTION:
g_value_set_enum (value, priv->direction);
break;
case PROP_CENTER_X:
g_value_set_int (value, priv->center_x);
break;
case PROP_CENTER_Y:
g_value_set_int (value, priv->center_y);
break;
case PROP_CENTER_Z:
g_value_set_int (value, priv->center_z);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
clutter_behaviour_rotate_class_init (ClutterBehaviourRotateClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterBehaviourClass *behaviour_class = CLUTTER_BEHAVIOUR_CLASS (klass);
GParamSpec *pspec = NULL;
gobject_class->set_property = clutter_behaviour_rotate_set_property;
gobject_class->get_property = clutter_behaviour_rotate_get_property;
behaviour_class->alpha_notify = clutter_behaviour_rotate_alpha_notify;
/**
* ClutterBehaviourRotate:angle-start:
*
* The initial angle from whence the rotation should start.
*
* Since: 0.4
*/
pspec = g_param_spec_double ("angle-start",
P_("Angle Begin"),
P_("Initial angle"),
0.0, 360.0,
0.0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_ANGLE_START] = pspec;
g_object_class_install_property (gobject_class,
PROP_ANGLE_START,
pspec);
/**
* ClutterBehaviourRotate:angle-end:
*
* The final angle to where the rotation should end.
*
* Since: 0.4
*/
pspec = g_param_spec_double ("angle-end",
P_("Angle End"),
P_("Final angle"),
0.0, 360.0,
0.0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_ANGLE_END] = pspec;
g_object_class_install_property (gobject_class,
PROP_ANGLE_END,
pspec);
/**
* ClutterBehaviourRotate:axis:
*
* The axis of rotation.
*
* Since: 0.4
*/
pspec = g_param_spec_enum ("axis",
P_("Axis"),
P_("Axis of rotation"),
CLUTTER_TYPE_ROTATE_AXIS,
CLUTTER_Z_AXIS,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_AXIS] = pspec;
g_object_class_install_property (gobject_class,
PROP_AXIS,
pspec);
/**
* ClutterBehaviourRotate:direction:
*
* The direction of the rotation.
*
* Since: 0.4
*/
pspec = g_param_spec_enum ("direction",
P_("Direction"),
P_("Direction of rotation"),
CLUTTER_TYPE_ROTATE_DIRECTION,
CLUTTER_ROTATE_CW,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_DIRECTION] = pspec;
g_object_class_install_property (gobject_class,
PROP_DIRECTION,
pspec);
/**
* ClutterBehaviourRotate:center-x:
*
* The x center of rotation.
*
* Since: 0.4
*/
pspec = g_param_spec_int ("center-x",
P_("Center X"),
P_("X coordinate of the center of rotation"),
-G_MAXINT, G_MAXINT,
0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_CENTER_X] = pspec;
g_object_class_install_property (gobject_class,
PROP_CENTER_X,
pspec);
/**
* ClutterBehaviourRotate:center-y:
*
* The y center of rotation.
*
* Since: 0.4
*/
pspec = g_param_spec_int ("center-y",
P_("Center Y"),
P_("Y coordinate of the center of rotation"),
-G_MAXINT, G_MAXINT,
0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_CENTER_Y] = pspec;
g_object_class_install_property (gobject_class,
PROP_CENTER_Y,
pspec);
/**
* ClutterBehaviourRotate:center-z:
*
* The z center of rotation.
*
* Since: 0.4
*/
pspec = g_param_spec_int ("center-z",
P_("Center Z"),
P_("Z coordinate of the center of rotation"),
-G_MAXINT, G_MAXINT,
0,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_CENTER_Z] = pspec;
g_object_class_install_property (gobject_class,
PROP_CENTER_Z,
pspec);
}
static void
clutter_behaviour_rotate_init (ClutterBehaviourRotate *self)
{
self->priv = clutter_behaviour_rotate_get_instance_private (self);
self->priv->angle_start = 0.0;
self->priv->angle_end = 0.0;
self->priv->axis = CLUTTER_Z_AXIS;
self->priv->direction = CLUTTER_ROTATE_CW;
self->priv->center_x = 0;
self->priv->center_y = 0;
self->priv->center_z = 0;
}
/**
* clutter_behaviour_rotate_new:
* @alpha: (allow-none): a #ClutterAlpha instance, or %NULL
* @axis: the rotation axis
* @direction: the rotation direction
* @angle_start: the starting angle in degrees, between 0 and 360.
* @angle_end: the final angle in degrees, between 0 and 360.
*
* Creates a new #ClutterBehaviourRotate. This behaviour will rotate actors
* bound to it on @axis, following @direction, between @angle_start and
* @angle_end. Angles >= 360 degrees will be clamped to the canonical interval
* <0, 360), if angle_start == angle_end, the behaviour will carry out a
* single rotation of 360 degrees.
*
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
* of the #ClutterAlpha instance. In the case when @alpha is %NULL,
* it can be set later with clutter_behaviour_set_alpha().
*
* Return value: the newly created #ClutterBehaviourRotate.
*
* Since: 0.4
*/
ClutterBehaviour *
clutter_behaviour_rotate_new (ClutterAlpha *alpha,
ClutterRotateAxis axis,
ClutterRotateDirection direction,
gdouble angle_start,
gdouble angle_end)
{
g_return_val_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha), NULL);
return g_object_new (CLUTTER_TYPE_BEHAVIOUR_ROTATE,
"alpha", alpha,
"axis", axis,
"direction", direction,
"angle-start", angle_start,
"angle-end", angle_end,
NULL);
}
/**
* clutter_behaviour_rotate_get_axis:
* @rotate: a #ClutterBehaviourRotate
*
* Retrieves the #ClutterRotateAxis used by the rotate behaviour.
*
* Return value: the rotation axis
*
* Since: 0.4
*/
ClutterRotateAxis
clutter_behaviour_rotate_get_axis (ClutterBehaviourRotate *rotate)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate), CLUTTER_Z_AXIS);
return rotate->priv->axis;
}
/**
* clutter_behaviour_rotate_set_axis:
* @rotate: a #ClutterBehaviourRotate
* @axis: a #ClutterRotateAxis
*
* Sets the axis used by the rotate behaviour.
*
* Since: 0.4
*/
void
clutter_behaviour_rotate_set_axis (ClutterBehaviourRotate *rotate,
ClutterRotateAxis axis)
{
ClutterBehaviourRotatePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate));
priv = rotate->priv;
if (priv->axis != axis)
{
priv->axis = axis;
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_AXIS]);
}
}
/**
* clutter_behaviour_rotate_get_direction:
* @rotate: a #ClutterBehaviourRotate
*
* Retrieves the #ClutterRotateDirection used by the rotate behaviour.
*
* Return value: the rotation direction
*
* Since: 0.4
*/
ClutterRotateDirection
clutter_behaviour_rotate_get_direction (ClutterBehaviourRotate *rotate)
{
g_return_val_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate),
CLUTTER_ROTATE_CW);
return rotate->priv->direction;
}
/**
* clutter_behaviour_rotate_set_direction:
* @rotate: a #ClutterBehaviourRotate
* @direction: the rotation direction
*
* Sets the rotation direction used by the rotate behaviour.
*
* Since: 0.4
*/
void
clutter_behaviour_rotate_set_direction (ClutterBehaviourRotate *rotate,
ClutterRotateDirection direction)
{
ClutterBehaviourRotatePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate));
priv = rotate->priv;
if (priv->direction != direction)
{
priv->direction = direction;
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_DIRECTION]);
}
}
/**
* clutter_behaviour_rotate_get_bounds:
* @rotate: a #ClutterBehaviourRotate
* @angle_start: (out): return value for the initial angle
* @angle_end: (out): return value for the final angle
*
* Retrieves the rotation boundaries of the rotate behaviour.
*
* Since: 0.4
*/
void
clutter_behaviour_rotate_get_bounds (ClutterBehaviourRotate *rotate,
gdouble *angle_start,
gdouble *angle_end)
{
ClutterBehaviourRotatePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate));
priv = rotate->priv;
if (angle_start)
*angle_start = priv->angle_start;
if (angle_end)
*angle_end = priv->angle_end;
}
/**
* clutter_behaviour_rotate_set_bounds:
* @rotate: a #ClutterBehaviourRotate
* @angle_start: initial angle in degrees, between 0 and 360.
* @angle_end: final angle in degrees, between 0 and 360.
*
* Sets the initial and final angles of a rotation behaviour; angles >= 360
* degrees get clamped to the canonical interval <0, 360).
*
* Since: 0.4
*/
void
clutter_behaviour_rotate_set_bounds (ClutterBehaviourRotate *rotate,
gdouble angle_start,
gdouble angle_end)
{
ClutterBehaviourRotatePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate));
priv = rotate->priv;
g_object_freeze_notify (G_OBJECT (rotate));
if (priv->angle_start != angle_start)
{
priv->angle_start = clamp_angle (angle_start);
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_ANGLE_START]);
}
if (priv->angle_end != angle_end)
{
priv->angle_end = clamp_angle (angle_end);
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_ANGLE_END]);
}
g_object_thaw_notify (G_OBJECT (rotate));
}
/**
* clutter_behaviour_rotate_set_center:
* @rotate: a #ClutterBehaviourRotate
* @x: X axis center of rotation
* @y: Y axis center of rotation
* @z: Z axis center of rotation
*
* Sets the center of rotation. The coordinates are relative to the plane
* normal to the rotation axis set with clutter_behaviour_rotate_set_axis().
*
* Since: 0.4
*/
void
clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate,
gint x,
gint y,
gint z)
{
ClutterBehaviourRotatePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate));
priv = rotate->priv;
g_object_freeze_notify (G_OBJECT (rotate));
if (priv->center_x != x)
{
priv->center_x = x;
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_CENTER_X]);
}
if (priv->center_y != y)
{
priv->center_y = y;
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_CENTER_Y]);
}
if (priv->center_z != z)
{
priv->center_z = z;
g_object_notify_by_pspec (G_OBJECT (rotate), obj_props[PROP_CENTER_Z]);
}
g_object_thaw_notify (G_OBJECT (rotate));
}
/**
* clutter_behaviour_rotate_get_center:
* @rotate: a #ClutterBehaviourRotate
* @x: (out): return location for the X center of rotation
* @y: (out): return location for the Y center of rotation
* @z: (out): return location for the Z center of rotation
*
* Retrieves the center of rotation set using
* clutter_behaviour_rotate_set_center().
*
* Since: 0.4
*/
void
clutter_behaviour_rotate_get_center (ClutterBehaviourRotate *rotate,
gint *x,
gint *y,
gint *z)
{
ClutterBehaviourRotatePrivate *priv;
g_return_if_fail (CLUTTER_IS_BEHAVIOUR_ROTATE (rotate));
priv = rotate->priv;
if (x)
*x = priv->center_x;
if (y)
*y = priv->center_y;
if (z)
*z = priv->center_z;
}

View File

@ -1,119 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2007 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_BEHAVIOUR_ROTATE_H__
#define __CLUTTER_BEHAVIOUR_ROTATE_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_BEHAVIOUR_ROTATE (clutter_behaviour_rotate_get_type ())
#define CLUTTER_BEHAVIOUR_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotate))
#define CLUTTER_IS_BEHAVIOUR_ROTATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BEHAVIOUR_ROTATE))
#define CLUTTER_BEHAVIOUR_ROTATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotateClass))
#define CLUTTER_IS_BEHAVIOUR_ROTATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BEHAVIOUR_ROTATE))
#define CLUTTER_BEHAVIOUR_ROTATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((klass), CLUTTER_TYPE_BEHAVIOUR_ROTATE, ClutterBehaviourRotateClass))
typedef struct _ClutterBehaviourRotate ClutterBehaviourRotate;
typedef struct _ClutterBehaviourRotatePrivate ClutterBehaviourRotatePrivate;
typedef struct _ClutterBehaviourRotateClass ClutterBehaviourRotateClass;
/**
* ClutterBehaviourRotate:
*
* The #ClutterBehaviourRotate struct contains only private data and
* should be accessed using the provided API
*
* Since: 0.4
*
* Deprecated: 1.6: Use clutter_actor_animate() instead.
*/
struct _ClutterBehaviourRotate
{
/*< private >*/
ClutterBehaviour parent_instance;
ClutterBehaviourRotatePrivate *priv;
};
/**
* ClutterBehaviourRotateClass:
*
* The #ClutterBehaviourRotateClass struct contains only private data
*
* Since: 0.4
*
* Deprecated: 1.6
*/
struct _ClutterBehaviourRotateClass
{
/*< private >*/
ClutterBehaviourClass parent_class;
};
CLUTTER_DEPRECATED
GType clutter_behaviour_rotate_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_actor_animate)
ClutterBehaviour * clutter_behaviour_rotate_new (ClutterAlpha *alpha,
ClutterRotateAxis axis,
ClutterRotateDirection direction,
gdouble angle_start,
gdouble angle_end);
CLUTTER_DEPRECATED
void clutter_behaviour_rotate_get_center (ClutterBehaviourRotate *rotate,
gint *x,
gint *y,
gint *z);
CLUTTER_DEPRECATED
void clutter_behaviour_rotate_set_center (ClutterBehaviourRotate *rotate,
gint x,
gint y,
gint z);
CLUTTER_DEPRECATED
ClutterRotateAxis clutter_behaviour_rotate_get_axis (ClutterBehaviourRotate *rotate);
CLUTTER_DEPRECATED
void clutter_behaviour_rotate_set_axis (ClutterBehaviourRotate *rotate,
ClutterRotateAxis axis);
CLUTTER_DEPRECATED
ClutterRotateDirection clutter_behaviour_rotate_get_direction (ClutterBehaviourRotate *rotate);
CLUTTER_DEPRECATED
void clutter_behaviour_rotate_set_direction (ClutterBehaviourRotate *rotate,
ClutterRotateDirection direction);
CLUTTER_DEPRECATED
void clutter_behaviour_rotate_get_bounds (ClutterBehaviourRotate *rotate,
gdouble *angle_start,
gdouble *angle_end);
CLUTTER_DEPRECATED
void clutter_behaviour_rotate_set_bounds (ClutterBehaviourRotate *rotate,
gdouble angle_start,
gdouble angle_end);
G_END_DECLS
#endif /* __CLUTTER_BEHAVIOUR_ROTATE_H__ */

View File

@ -101,7 +101,8 @@ enum
static GParamSpec *obj_props[PROP_LAST];
enum {
enum
{
APPLIED,
REMOVED,
LAST_SIGNAL

View File

@ -1,261 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2008 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-main.h"
#include "clutter-private.h"
#include "deprecated/clutter-frame-source.h"
#include "deprecated/clutter-timeout-interval.h"
typedef struct _ClutterFrameSource ClutterFrameSource;
struct _ClutterFrameSource
{
GSource source;
ClutterTimeoutInterval timeout;
};
static gboolean clutter_frame_source_prepare (GSource *source,
gint *timeout);
static gboolean clutter_frame_source_check (GSource *source);
static gboolean clutter_frame_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data);
static GSourceFuncs clutter_frame_source_funcs =
{
clutter_frame_source_prepare,
clutter_frame_source_check,
clutter_frame_source_dispatch,
NULL
};
/**
* clutter_frame_source_add_full: (rename-to clutter_frame_source_add)
* @priority: the priority of the frame source. Typically this will be in the
* range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
* @fps: the number of times per second to call the function
* @func: function to call
* @data: data to pass to the function
* @notify: function to call when the timeout source is removed
*
* Sets a function to be called at regular intervals with the given
* priority. The function is called repeatedly until it returns
* %FALSE, at which point the timeout is automatically destroyed and
* the function will not be called again. The @notify function is
* called when the timeout is destroyed. The first call to the
* function will be at the end of the first @interval.
*
* This function is similar to g_timeout_add_full() except that it
* will try to compensate for delays. For example, if @func takes half
* the interval time to execute then the function will be called again
* half the interval time after it finished. In contrast
* g_timeout_add_full() would not fire until a full interval after the
* function completes so the delay between calls would be 1.0 / @fps *
* 1.5. This function does not however try to invoke the function
* multiple times to catch up missing frames if @func takes more than
* @interval ms to execute.
*
* Return value: the ID (greater than 0) of the event source.
*
* Since: 0.8
*
* Deprecated: 1.6: There is no direct replacement for this API.
*/
guint
clutter_frame_source_add_full (gint priority,
guint fps,
GSourceFunc func,
gpointer data,
GDestroyNotify notify)
{
guint ret;
GSource *source = g_source_new (&clutter_frame_source_funcs,
sizeof (ClutterFrameSource));
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
_clutter_timeout_interval_init (&frame_source->timeout, fps);
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority (source, priority);
g_source_set_name (source, "Clutter frame timeout");
g_source_set_callback (source, func, data, notify);
ret = g_source_attach (source, NULL);
g_source_unref (source);
return ret;
}
/**
* clutter_frame_source_add: (skip)
* @fps: the number of times per second to call the function
* @func: function to call
* @data: data to pass to the function
*
* Simple wrapper around clutter_frame_source_add_full().
*
* Return value: the ID (greater than 0) of the event source.
*
* Since: 0.8
*
* Deprecated: 1.6: There is no direct replacement for this API
*/
guint
clutter_frame_source_add (guint fps,
GSourceFunc func,
gpointer data)
{
return clutter_frame_source_add_full (G_PRIORITY_DEFAULT,
fps, func, data, NULL);
}
static gboolean
clutter_frame_source_prepare (GSource *source,
gint *delay)
{
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
gint64 current_time;
#if GLIB_CHECK_VERSION (2, 27, 3)
current_time = g_source_get_time (source) / 1000;
#else
{
GTimeVal source_time;
g_source_get_current_time (source, &source_time);
current_time = source_time.tv_sec * 1000 + source_time.tv_usec / 1000;
}
#endif
return _clutter_timeout_interval_prepare (current_time,
&frame_source->timeout,
delay);
}
static gboolean
clutter_frame_source_check (GSource *source)
{
return clutter_frame_source_prepare (source, NULL);
}
static gboolean
clutter_frame_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterFrameSource *frame_source = (ClutterFrameSource *) source;
return _clutter_timeout_interval_dispatch (&frame_source->timeout,
callback, user_data);
}
/**
* clutter_threads_add_frame_source_full: (rename-to clutter_threads_add_frame_source)
* @priority: the priority of the frame source. Typically this will be in the
* range between %G_PRIORITY_DEFAULT and %G_PRIORITY_HIGH.
* @fps: the number of times per second to call the function
* @func: function to call
* @data: data to pass to the function
* @notify: function to call when the timeout source is removed
*
* Sets a function to be called at regular intervals holding the Clutter
* threads lock, with the given priority. The function is called repeatedly
* until it returns %FALSE, at which point the timeout is automatically
* removed and the function will not be called again. The @notify function
* is called when the timeout is removed.
*
* This function is similar to clutter_threads_add_timeout_full()
* except that it will try to compensate for delays. For example, if
* @func takes half the interval time to execute then the function
* will be called again half the interval time after it finished. In
* contrast clutter_threads_add_timeout_full() would not fire until a
* full interval after the function completes so the delay between
* calls would be @interval * 1.5. This function does not however try
* to invoke the function multiple times to catch up missing frames if
* @func takes more than @interval ms to execute.
*
* See also clutter_threads_add_idle_full().
*
* Return value: the ID (greater than 0) of the event source.
*
* Since: 0.8
*
* Deprecated: 1.6: There is no direct replacement for this API
*/
guint
clutter_threads_add_frame_source_full (gint priority,
guint fps,
GSourceFunc func,
gpointer data,
GDestroyNotify notify)
{
ClutterThreadsDispatch *dispatch;
g_return_val_if_fail (func != NULL, 0);
dispatch = g_slice_new (ClutterThreadsDispatch);
dispatch->func = func;
dispatch->data = data;
dispatch->notify = notify;
return clutter_frame_source_add_full (priority,
fps,
_clutter_threads_dispatch, dispatch,
_clutter_threads_dispatch_free);
}
/**
* clutter_threads_add_frame_source: (skip)
* @fps: the number of times per second to call the function
* @func: function to call
* @data: data to pass to the function
*
* Simple wrapper around clutter_threads_add_frame_source_full().
*
* Return value: the ID (greater than 0) of the event source.
*
* Since: 0.8
*
* Deprecated: 1.6: There is no direct replacement for this API
*/
guint
clutter_threads_add_frame_source (guint fps,
GSourceFunc func,
gpointer data)
{
g_return_val_if_fail (func != NULL, 0);
return clutter_threads_add_frame_source_full (G_PRIORITY_DEFAULT,
fps,
func, data,
NULL);
}

View File

@ -1,49 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2008 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_FRAME_SOURCE_H__
#define __CLUTTER_FRAME_SOURCE_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
CLUTTER_DEPRECATED
guint clutter_frame_source_add (guint fps,
GSourceFunc func,
gpointer data);
CLUTTER_DEPRECATED
guint clutter_frame_source_add_full (gint priority,
guint fps,
GSourceFunc func,
gpointer data,
GDestroyNotify notify);
G_END_DECLS
#endif /* __CLUTTER_FRAME_SOURCE_H__ */

View File

@ -1,36 +0,0 @@
#include "clutter-build-config.h"
#include <glib-object.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-device-manager-private.h"
#include "deprecated/clutter-input-device.h"
/**
* clutter_input_device_get_device_coords:
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
* @x: (out): return location for the X coordinate
* @y: (out): return location for the Y coordinate
*
* Retrieves the latest coordinates of the pointer of @device
*
* Since: 1.2
*
* Deprecated: 1.12: Use clutter_input_device_get_coords() instead.
*/
void
clutter_input_device_get_device_coords (ClutterInputDevice *device,
gint *x,
gint *y)
{
ClutterPoint point;
clutter_input_device_get_coords (device, NULL, &point);
if (x)
*x = point.x;
if (y)
*y = point.y;
}

View File

@ -1,41 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright © 2009, 2010, 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/>.
*
* 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_INPUT_DEVICE_DEPRECATED_H__
#define __CLUTTER_INPUT_DEVICE_DEPRECATED_H__
#include <clutter/clutter-input-device.h>
G_BEGIN_DECLS
CLUTTER_DEPRECATED_FOR(clutter_input_device_get_coords)
void clutter_input_device_get_device_coords (ClutterInputDevice *device,
gint *x,
gint *y);
G_END_DECLS
#endif /* __CLUTTER_INPUT_DEVICE_DEPRECATED_H__ */

View File

@ -1,834 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Neil Jagdish Patel <njp@o-hand.com>
* Emmanuele Bassi <ebassi@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-list-model
* @short_description: List model implementation
*
* #ClutterListModel is a #ClutterModel implementation provided by
* Clutter. #ClutterListModel uses a #GSequence for storing the
* values for each row, so it's optimized for insertion and look up
* in sorted lists.
*
* #ClutterListModel is available since Clutter 0.6
*
* Deprecated: 1.24: Use a #GListStore instance containing a custom
* object type with properties for each column instead.
*/
#include "clutter-build-config.h"
#include <stdlib.h>
#include <string.h>
#include <glib-object.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-list-model.h"
#include "clutter-model.h"
#include "clutter-model-private.h"
#include "clutter-private.h"
#include "clutter-debug.h"
#define CLUTTER_TYPE_LIST_MODEL_ITER \
(clutter_list_model_iter_get_type())
#define CLUTTER_LIST_MODEL_ITER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), \
CLUTTER_TYPE_LIST_MODEL_ITER, \
ClutterListModelIter))
#define CLUTTER_IS_LIST_MODEL_ITER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj), \
CLUTTER_TYPE_LIST_MODEL_ITER))
#define CLUTTER_LIST_MODEL_ITER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
CLUTTER_TYPE_LIST_MODEL_ITER, \
ClutterListModelIterClass))
#define CLUTTER_IS_LIST_MODEL_ITER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
CLUTTER_TYPE_LIST_MODEL_ITER))
#define CLUTTER_LIST_MODEL_ITER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
CLUTTER_TYPE_LIST_MODEL_ITER, \
ClutterListModelIterClass))
typedef struct _ClutterListModelIter ClutterListModelIter;
typedef struct _ClutterModelIterClass ClutterListModelIterClass;
struct _ClutterListModelPrivate
{
GSequence *sequence;
ClutterModelIter *temp_iter;
};
struct _ClutterListModelIter
{
ClutterModelIter parent_instance;
GSequenceIter *seq_iter;
};
GType clutter_list_model_iter_get_type (void);
/*
* ClutterListModel
*/
G_DEFINE_TYPE (ClutterListModelIter,
clutter_list_model_iter,
CLUTTER_TYPE_MODEL_ITER)
static void
clutter_list_model_iter_get_value (ClutterModelIter *iter,
guint column,
GValue *value)
{
ClutterListModelIter *iter_default;
GValue *values;
GValue *iter_value;
GValue real_value = G_VALUE_INIT;
gboolean converted = FALSE;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
g_assert (iter_default->seq_iter != NULL);
values = g_sequence_get (iter_default->seq_iter);
iter_value = &values[column];
g_assert (iter_value != NULL);
if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value)))
{
if (!g_value_type_compatible (G_VALUE_TYPE (value),
G_VALUE_TYPE (iter_value)) &&
!g_value_type_compatible (G_VALUE_TYPE (iter_value),
G_VALUE_TYPE (value)))
{
g_warning ("%s: Unable to convert from %s to %s",
G_STRLOC,
g_type_name (G_VALUE_TYPE (value)),
g_type_name (G_VALUE_TYPE (iter_value)));
return;
}
if (!g_value_transform (iter_value, &real_value))
{
g_warning ("%s: Unable to make conversion from %s to %s",
G_STRLOC,
g_type_name (G_VALUE_TYPE (value)),
g_type_name (G_VALUE_TYPE (iter_value)));
g_value_unset (&real_value);
}
converted = TRUE;
}
if (converted)
{
g_value_copy (&real_value, value);
g_value_unset (&real_value);
}
else
g_value_copy (iter_value, value);
}
static void
clutter_list_model_iter_set_value (ClutterModelIter *iter,
guint column,
const GValue *value)
{
ClutterListModelIter *iter_default;
GValue *values;
GValue *iter_value;
GValue real_value = G_VALUE_INIT;
gboolean converted = FALSE;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
g_assert (iter_default->seq_iter != NULL);
values = g_sequence_get (iter_default->seq_iter);
iter_value = &values[column];
g_assert (iter_value != NULL);
if (!g_type_is_a (G_VALUE_TYPE (value), G_VALUE_TYPE (iter_value)))
{
if (!g_value_type_compatible (G_VALUE_TYPE (value),
G_VALUE_TYPE (iter_value)) &&
!g_value_type_compatible (G_VALUE_TYPE (iter_value),
G_VALUE_TYPE (value)))
{
g_warning ("%s: Unable to convert from %s to %s\n",
G_STRLOC,
g_type_name (G_VALUE_TYPE (value)),
g_type_name (G_VALUE_TYPE (iter_value)));
return;
}
if (!g_value_transform (value, &real_value))
{
g_warning ("%s: Unable to make conversion from %s to %s\n",
G_STRLOC,
g_type_name (G_VALUE_TYPE (value)),
g_type_name (G_VALUE_TYPE (iter_value)));
g_value_unset (&real_value);
}
converted = TRUE;
}
if (converted)
{
g_value_copy (&real_value, iter_value);
g_value_unset (&real_value);
}
else
g_value_copy (value, iter_value);
}
static gboolean
clutter_list_model_iter_is_first (ClutterModelIter *iter)
{
ClutterListModelIter *iter_default;
ClutterModel *model;
ClutterModelIter *temp_iter;
GSequence *sequence;
GSequenceIter *begin, *end;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
g_assert (iter_default->seq_iter != NULL);
model = clutter_model_iter_get_model (iter);
sequence = CLUTTER_LIST_MODEL (model)->priv->sequence;
begin = g_sequence_get_begin_iter (sequence);
end = iter_default->seq_iter;
temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter;
while (!g_sequence_iter_is_begin (begin))
{
CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = begin;
if (clutter_model_filter_iter (model, temp_iter))
{
end = begin;
break;
}
begin = g_sequence_iter_next (begin);
}
/* This is because the 'begin_iter' is always *before* the last valid
* iter, otherwise we'd have endless loops
*/
end = g_sequence_iter_prev (end);
return iter_default->seq_iter == end;
}
static gboolean
clutter_list_model_iter_is_last (ClutterModelIter *iter)
{
ClutterListModelIter *iter_default;
ClutterModelIter *temp_iter;
ClutterModel *model;
GSequence *sequence;
GSequenceIter *begin, *end;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
g_assert (iter_default->seq_iter != NULL);
if (g_sequence_iter_is_end (iter_default->seq_iter))
return TRUE;
model = clutter_model_iter_get_model (iter);
sequence = CLUTTER_LIST_MODEL (model)->priv->sequence;
begin = g_sequence_get_end_iter (sequence);
begin = g_sequence_iter_prev (begin);
end = iter_default->seq_iter;
temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter;
while (!g_sequence_iter_is_begin (begin))
{
CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = begin;
if (clutter_model_filter_iter (model, temp_iter))
{
end = begin;
break;
}
begin = g_sequence_iter_prev (begin);
}
/* This is because the 'end_iter' is always *after* the last valid iter.
* Otherwise we'd have endless loops
*/
end = g_sequence_iter_next (end);
return iter_default->seq_iter == end;
}
static ClutterModelIter *
clutter_list_model_iter_next (ClutterModelIter *iter)
{
ClutterListModelIter *iter_default;
ClutterModelIter *temp_iter;
ClutterModel *model = NULL;
GSequenceIter *filter_next;
guint row;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
g_assert (iter_default->seq_iter != NULL);
model = clutter_model_iter_get_model (iter);
row = clutter_model_iter_get_row (iter);
filter_next = g_sequence_iter_next (iter_default->seq_iter);
g_assert (filter_next != NULL);
temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter;
while (!g_sequence_iter_is_end (filter_next))
{
CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = filter_next;
if (clutter_model_filter_iter (model, temp_iter))
{
row += 1;
break;
}
filter_next = g_sequence_iter_next (filter_next);
}
if (g_sequence_iter_is_end (filter_next))
row += 1;
/* update the iterator and return it */
_clutter_model_iter_set_row (CLUTTER_MODEL_ITER (iter_default), row);
iter_default->seq_iter = filter_next;
return CLUTTER_MODEL_ITER (iter_default);
}
static ClutterModelIter *
clutter_list_model_iter_prev (ClutterModelIter *iter)
{
ClutterListModelIter *iter_default;
ClutterModelIter *temp_iter;
ClutterModel *model;
GSequenceIter *filter_prev;
guint row;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
g_assert (iter_default->seq_iter != NULL);
model = clutter_model_iter_get_model (iter);
row = clutter_model_iter_get_row (iter);
filter_prev = g_sequence_iter_prev (iter_default->seq_iter);
g_assert (filter_prev != NULL);
temp_iter = CLUTTER_LIST_MODEL (model)->priv->temp_iter;
while (!g_sequence_iter_is_begin (filter_prev))
{
CLUTTER_LIST_MODEL_ITER (temp_iter)->seq_iter = filter_prev;
if (clutter_model_filter_iter (model, temp_iter))
{
row -= 1;
break;
}
filter_prev = g_sequence_iter_prev (filter_prev);
}
if (g_sequence_iter_is_begin (filter_prev))
row -= 1;
/* update the iterator and return it */
_clutter_model_iter_set_row (CLUTTER_MODEL_ITER (iter_default), row);
iter_default->seq_iter = filter_prev;
return CLUTTER_MODEL_ITER (iter_default);
}
static ClutterModelIter *
clutter_list_model_iter_copy (ClutterModelIter *iter)
{
ClutterListModelIter *iter_default;
ClutterListModelIter *iter_copy;
ClutterModel *model;
guint row;
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
model = clutter_model_iter_get_model (iter);
row = clutter_model_iter_get_row (iter) - 1;
iter_copy = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER,
"model", model,
"row", row,
NULL);
/* this is safe, because the seq_iter pointer on the passed
* iterator will be always be overwritten in ::next or ::prev
*/
iter_copy->seq_iter = iter_default->seq_iter;
return CLUTTER_MODEL_ITER (iter_copy);
}
static void
clutter_list_model_iter_class_init (ClutterListModelIterClass *klass)
{
ClutterModelIterClass *iter_class = CLUTTER_MODEL_ITER_CLASS (klass);
iter_class->get_value = clutter_list_model_iter_get_value;
iter_class->set_value = clutter_list_model_iter_set_value;
iter_class->is_first = clutter_list_model_iter_is_first;
iter_class->is_last = clutter_list_model_iter_is_last;
iter_class->next = clutter_list_model_iter_next;
iter_class->prev = clutter_list_model_iter_prev;
iter_class->copy = clutter_list_model_iter_copy;
}
static void
clutter_list_model_iter_init (ClutterListModelIter *iter)
{
iter->seq_iter = NULL;
}
/*
* ClutterListModel
*/
G_DEFINE_TYPE_WITH_PRIVATE (ClutterListModel, clutter_list_model, CLUTTER_TYPE_MODEL)
static ClutterModelIter *
clutter_list_model_get_iter_at_row (ClutterModel *model,
guint row)
{
ClutterListModel *model_default = CLUTTER_LIST_MODEL (model);
GSequence *sequence = model_default->priv->sequence;
GSequenceIter *filter_next;
gint seq_length = g_sequence_get_length (sequence);
ClutterListModelIter *retval;
gint count = -1;
if (row >= seq_length)
return NULL;
retval = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER,
"model", model,
"row", row,
NULL);
/* short-circuit in case we don't have a filter in place */
if (!clutter_model_get_filter_set (model))
{
retval->seq_iter = g_sequence_get_iter_at_pos (sequence, row);
return CLUTTER_MODEL_ITER (retval);
}
filter_next = g_sequence_get_begin_iter (sequence);
g_assert (filter_next != NULL);
while (!g_sequence_iter_is_end (filter_next))
{
retval->seq_iter = filter_next;
if (clutter_model_filter_iter (model, CLUTTER_MODEL_ITER (retval)))
{
/* We've found a row that is valid under the filter */
count++;
if (count == row)
break;
}
filter_next = g_sequence_iter_next (filter_next);
}
if (count != row)
{
g_object_unref (retval);
return NULL;
}
return CLUTTER_MODEL_ITER (retval);
}
static ClutterModelIter *
clutter_list_model_insert_row (ClutterModel *model,
gint index_)
{
ClutterListModel *model_default = CLUTTER_LIST_MODEL (model);
GSequence *sequence = model_default->priv->sequence;
ClutterListModelIter *retval;
guint n_columns, i, pos;
GValue *values;
GSequenceIter *seq_iter;
n_columns = clutter_model_get_n_columns (model);
values = g_new0 (GValue, n_columns);
for (i = 0; i < n_columns; i++)
g_value_init (&values[i], clutter_model_get_column_type (model, i));
if (index_ < 0)
{
seq_iter = g_sequence_append (sequence, values);
pos = g_sequence_get_length (sequence) - 1;
}
else if (index_ == 0)
{
seq_iter = g_sequence_prepend (sequence, values);
pos = 0;
}
else
{
seq_iter = g_sequence_get_iter_at_pos (sequence, index_);
seq_iter = g_sequence_insert_before (seq_iter, values);
pos = index_;
}
retval = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER,
"model", model,
"row", pos,
NULL);
retval->seq_iter = seq_iter;
return CLUTTER_MODEL_ITER (retval);
}
static void
clutter_list_model_remove_row (ClutterModel *model,
guint row)
{
ClutterListModel *model_default = CLUTTER_LIST_MODEL (model);
GSequence *sequence = model_default->priv->sequence;
GSequenceIter *seq_iter;
guint pos = 0;
seq_iter = g_sequence_get_begin_iter (sequence);
while (!g_sequence_iter_is_end (seq_iter))
{
if (clutter_model_filter_row (model, pos))
{
if (pos == row)
{
ClutterModelIter *iter;
iter = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER,
"model", model,
"row", pos,
NULL);
CLUTTER_LIST_MODEL_ITER (iter)->seq_iter = seq_iter;
/* the actual row is removed from the sequence inside
* the ::row-removed signal class handler, so that every
* handler connected to ::row-removed will still get
* a valid iterator, and every signal connected to
* ::row-removed with the AFTER flag will get an updated
* model
*/
g_signal_emit_by_name (model, "row-removed", iter);
g_object_unref (iter);
break;
}
}
pos += 1;
seq_iter = g_sequence_iter_next (seq_iter);
}
}
typedef struct
{
ClutterModel *model;
guint column;
ClutterModelSortFunc func;
gpointer data;
} SortClosure;
static gint
sort_model_default (gconstpointer a,
gconstpointer b,
gpointer data)
{
const GValue *row_a = a;
const GValue *row_b = b;
SortClosure *clos = data;
return clos->func (clos->model,
&row_a[clos->column],
&row_b[clos->column],
clos->data);
}
static void
clutter_list_model_resort (ClutterModel *model,
ClutterModelSortFunc func,
gpointer data)
{
SortClosure sort_closure = { NULL, 0, NULL, NULL };
sort_closure.model = model;
sort_closure.column = clutter_model_get_sorting_column (model);
sort_closure.func = func;
sort_closure.data = data;
g_sequence_sort (CLUTTER_LIST_MODEL (model)->priv->sequence,
sort_model_default,
&sort_closure);
}
static guint
clutter_list_model_get_n_rows (ClutterModel *model)
{
ClutterListModel *list_model = CLUTTER_LIST_MODEL (model);
/* short-circuit in case we don't have a filter in place */
if (!clutter_model_get_filter_set (model))
return g_sequence_get_length (list_model->priv->sequence);
return CLUTTER_MODEL_CLASS (clutter_list_model_parent_class)->get_n_rows (model);
}
static void
clutter_list_model_row_removed (ClutterModel *model,
ClutterModelIter *iter)
{
ClutterListModelIter *iter_default;
guint i, n_columns;
GValue *values;
n_columns = clutter_model_get_n_columns (model);
iter_default = CLUTTER_LIST_MODEL_ITER (iter);
values = g_sequence_get (iter_default->seq_iter);
for (i = 0; i < n_columns; i++)
g_value_unset (&values[i]);
g_free (values);
g_sequence_remove (iter_default->seq_iter);
iter_default->seq_iter = NULL;
}
static void
clutter_list_model_finalize (GObject *gobject)
{
ClutterListModel *model = CLUTTER_LIST_MODEL (gobject);
GSequence *sequence = model->priv->sequence;
GSequenceIter *iter;
guint n_columns, i;
n_columns = clutter_model_get_n_columns (CLUTTER_MODEL (gobject));
iter = g_sequence_get_begin_iter (sequence);
while (!g_sequence_iter_is_end (iter))
{
GValue *values = g_sequence_get (iter);
for (i = 0; i < n_columns; i++)
g_value_unset (&values[i]);
g_free (values);
iter = g_sequence_iter_next (iter);
}
g_sequence_free (sequence);
G_OBJECT_CLASS (clutter_list_model_parent_class)->finalize (gobject);
}
static void
clutter_list_model_dispose (GObject *gobject)
{
ClutterListModel *model = CLUTTER_LIST_MODEL (gobject);
if (model->priv->temp_iter)
{
g_object_unref (model->priv->temp_iter);
model->priv->temp_iter = NULL;
}
G_OBJECT_CLASS (clutter_list_model_parent_class)->dispose (gobject);
}
static void
clutter_list_model_class_init (ClutterListModelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterModelClass *model_class = CLUTTER_MODEL_CLASS (klass);
gobject_class->finalize = clutter_list_model_finalize;
gobject_class->dispose = clutter_list_model_dispose;
model_class->get_iter_at_row = clutter_list_model_get_iter_at_row;
model_class->insert_row = clutter_list_model_insert_row;
model_class->remove_row = clutter_list_model_remove_row;
model_class->resort = clutter_list_model_resort;
model_class->get_n_rows = clutter_list_model_get_n_rows;
model_class->row_removed = clutter_list_model_row_removed;
}
static void
clutter_list_model_init (ClutterListModel *model)
{
model->priv = clutter_list_model_get_instance_private (model);
model->priv->sequence = g_sequence_new (NULL);
model->priv->temp_iter = g_object_new (CLUTTER_TYPE_LIST_MODEL_ITER,
"model",
model,
NULL);
}
/**
* clutter_list_model_new:
* @n_columns: number of columns in the model
* @...: @n_columns number of #GType and string pairs
*
* Creates a new default model with @n_columns columns with the types
* and names passed in.
*
* For example:
*
* <informalexample><programlisting>
* model = clutter_list_model_new (3,
* G_TYPE_INT, "Score",
* G_TYPE_STRING, "Team",
* GDK_TYPE_PIXBUF, "Logo");
* </programlisting></informalexample>
*
* will create a new #ClutterModel with three columns of type int,
* string and #GdkPixbuf respectively.
*
* Note that the name of the column can be set to %NULL, in which case
* the canonical name of the type held by the column will be used as
* the title.
*
* Return value: a new #ClutterListModel
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListStore instead
*/
ClutterModel *
clutter_list_model_new (guint n_columns,
...)
{
ClutterModel *model;
va_list args;
gint i;
g_return_val_if_fail (n_columns > 0, NULL);
model = g_object_new (CLUTTER_TYPE_LIST_MODEL, NULL);
_clutter_model_set_n_columns (model, n_columns, TRUE, TRUE);
va_start (args, n_columns);
for (i = 0; i < n_columns; i++)
{
GType type = va_arg (args, GType);
const gchar *name = va_arg (args, gchar*);
if (!_clutter_model_check_type (type))
{
g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
g_object_unref (model);
model = NULL;
goto out;
}
_clutter_model_set_column_type (model, i, type);
_clutter_model_set_column_name (model, i, name);
}
out:
va_end (args);
return model;
}
/**
* clutter_list_model_newv:
* @n_columns: number of columns in the model
* @types: (array length=n_columns): an array of #GType types for the columns, from first to last
* @names: (array length=n_columns): an array of names for the columns, from first to last
*
* Non-vararg version of clutter_list_model_new(). This function is
* useful for language bindings.
*
* Return value: (transfer full): a new default #ClutterModel
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListStore instead
*/
ClutterModel *
clutter_list_model_newv (guint n_columns,
GType *types,
const gchar * const names[])
{
ClutterModel *model;
gint i;
g_return_val_if_fail (n_columns > 0, NULL);
model = g_object_new (CLUTTER_TYPE_LIST_MODEL, NULL);
_clutter_model_set_n_columns (model, n_columns, TRUE, TRUE);
for (i = 0; i < n_columns; i++)
{
if (!_clutter_model_check_type (types[i]))
{
g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (types[i]));
g_object_unref (model);
return NULL;
}
_clutter_model_set_column_type (model, i, types[i]);
_clutter_model_set_column_name (model, i, names[i]);
}
return model;
}

View File

@ -1,95 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Neil Jagdish Patel <njp@o-hand.com>
* Emmanuele Bassi <ebassi@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/>.
*
* NB: Inspiration for column storage taken from GtkListStore
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_LIST_MODEL_H__
#define __CLUTTER_LIST_MODEL_H__
#include <clutter/deprecated/clutter-model.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_LIST_MODEL (clutter_list_model_get_type ())
#define CLUTTER_LIST_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LIST_MODEL, ClutterListModel))
#define CLUTTER_IS_LIST_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LIST_MODEL))
#define CLUTTER_LIST_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_LIST_MODEL, ClutterListModeClass))
#define CLUTTER_IS_LIST_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_LIST_MODEL))
#define CLUTTER_LIST_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_LIST_MODEL, ClutterListModeClass))
typedef struct _ClutterListModel ClutterListModel;
typedef struct _ClutterListModelPrivate ClutterListModelPrivate;
typedef struct _ClutterListModelClass ClutterListModelClass;
/**
* ClutterListModel:
*
* The #ClutterListModel struct contains only private data.
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListStore instead
*/
struct _ClutterListModel
{
/*< private >*/
ClutterModel parent_instance;
ClutterListModelPrivate *priv;
};
/**
* ClutterListModelClass:
*
* The #ClutterListModelClass struct contains only private data.
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListStore instead
*/
struct _ClutterListModelClass
{
/*< private >*/
ClutterModelClass parent_class;
};
CLUTTER_DEPRECATED_FOR(g_list_store_get_type)
GType clutter_list_model_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(g_list_store_new)
ClutterModel *clutter_list_model_new (guint n_columns,
...);
CLUTTER_DEPRECATED_FOR(g_list_store_new)
ClutterModel *clutter_list_model_newv (guint n_columns,
GType *types,
const gchar * const names[]);
G_END_DECLS
#endif /* __CLUTTER_LIST_MODEL_H__ */

View File

@ -40,17 +40,6 @@ void clutter_threads_enter (void);
CLUTTER_DEPRECATED
void clutter_threads_leave (void);
CLUTTER_DEPRECATED
guint clutter_threads_add_frame_source (guint fps,
GSourceFunc func,
gpointer data);
CLUTTER_DEPRECATED
guint clutter_threads_add_frame_source_full (gint priority,
guint fps,
GSourceFunc func,
gpointer data,
GDestroyNotify notify);
CLUTTER_DEPRECATED_FOR(clutter_stage_set_motion_events_enabled)
void clutter_set_motion_events_enabled (gboolean enable);

View File

@ -1,52 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Neil Jagdish Patel <njp@o-hand.com>
* Emmanuele Bassi <ebassi@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_MODEL_PRIVATE_H__
#define __CLUTTER_MODEL_PRIVATE_H__
#include "clutter-types.h"
#include "clutter-model.h"
G_BEGIN_DECLS
void _clutter_model_set_n_columns (ClutterModel *model,
gint n_columns,
gboolean set_types,
gboolean set_names);
gboolean _clutter_model_check_type (GType gtype);
void _clutter_model_set_column_type (ClutterModel *model,
gint column,
GType gtype);
void _clutter_model_set_column_name (ClutterModel *model,
gint column,
const gchar *name);
void _clutter_model_iter_set_row (ClutterModelIter *iter,
guint row);
G_END_DECLS
#endif /* __CLUTTER_MODEL_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,436 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Neil Jagdish Patel <njp@o-hand.com>
* Emmanuele Bassi <ebassi@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_MODEL_H__
#define __CLUTTER_MODEL_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_MODEL (clutter_model_get_type ())
#define CLUTTER_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MODEL, ClutterModel))
#define CLUTTER_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_MODEL, ClutterModelClass))
#define CLUTTER_IS_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MODEL))
#define CLUTTER_IS_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_MODEL))
#define CLUTTER_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MODEL, ClutterModelClass))
typedef struct _ClutterModel ClutterModel;
typedef struct _ClutterModelClass ClutterModelClass;
typedef struct _ClutterModelPrivate ClutterModelPrivate;
typedef struct _ClutterModelIter ClutterModelIter;
typedef struct _ClutterModelIterClass ClutterModelIterClass;
typedef struct _ClutterModelIterPrivate ClutterModelIterPrivate;
/**
* ClutterModelFilterFunc:
* @model: a #ClutterModel
* @iter: the iterator for the row
* @user_data: data passed to clutter_model_set_filter()
*
* Filters the content of a row in the model.
*
* Return value: If the row should be displayed, return %TRUE
*
* Since: 0.6
*
* Deprecated: 1.24: Implement filters using a custom #GListModel instead
*/
typedef gboolean (*ClutterModelFilterFunc) (ClutterModel *model,
ClutterModelIter *iter,
gpointer user_data);
/**
* ClutterModelSortFunc:
* @model: a #ClutterModel
* @a: a #GValue representing the contents of the row
* @b: a #GValue representing the contents of the second row
* @user_data: data passed to clutter_model_set_sort()
*
* Compares the content of two rows in the model.
*
* Return value: a positive integer if @a is after @b, a negative integer if
* @a is before @b, or 0 if the rows are the same
*
* Since: 0.6
*
* Deprecated: 1.24: Implement sorting using a custom #GListModel instead
*/
typedef gint (*ClutterModelSortFunc) (ClutterModel *model,
const GValue *a,
const GValue *b,
gpointer user_data);
/**
* ClutterModelForeachFunc:
* @model: a #ClutterModel
* @iter: the iterator for the row
* @user_data: data passed to clutter_model_foreach()
*
* Iterates on the content of a row in the model
*
* Return value: %TRUE if the iteration should continue, %FALSE otherwise
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListModel
*/
typedef gboolean (*ClutterModelForeachFunc) (ClutterModel *model,
ClutterModelIter *iter,
gpointer user_data);
/**
* ClutterModel:
*
* Base class for list models. The #ClutterModel structure contains
* only private data and should be manipulated using the provided
* API.
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListModel instead
*/
struct _ClutterModel
{
/*< private >*/
GObject parent_instance;
ClutterModelPrivate *priv;
};
/**
* ClutterModelClass:
* @row_added: signal class handler for ClutterModel::row-added
* @row_removed: signal class handler for ClutterModel::row-removed
* @row_changed: signal class handler for ClutterModel::row-changed
* @sort_changed: signal class handler for ClutterModel::sort-changed
* @filter_changed: signal class handler for ClutterModel::filter-changed
* @get_column_name: virtual function for returning the name of a column
* @get_column_type: virtual function for returning the type of a column
* @get_iter_at_row: virtual function for returning an iterator for the
* given row
* @get_n_rows: virtual function for returning the number of rows
* of the model
* @get_n_columns: virtual function for retuning the number of columns
* of the model
* @resort: virtual function for sorting the model using the passed
* sorting function
* @insert_row: virtual function for inserting a row at the given index
* and returning an iterator pointing to it; if the index is a negative
* integer, the row should be appended to the model
* @remove_row: virtual function for removing a row at the given index
*
* Class for #ClutterModel instances.
*
* Since: 0.6
*
* Deprecated: 1.24: Use #GListModel instead
*/
struct _ClutterModelClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
/* vtable */
guint (* get_n_rows) (ClutterModel *model);
guint (* get_n_columns) (ClutterModel *model);
const gchar * (* get_column_name) (ClutterModel *model,
guint column);
GType (* get_column_type) (ClutterModel *model,
guint column);
ClutterModelIter *(* insert_row) (ClutterModel *model,
gint index_);
void (* remove_row) (ClutterModel *model,
guint row);
ClutterModelIter *(* get_iter_at_row) (ClutterModel *model,
guint row);
void (* resort) (ClutterModel *model,
ClutterModelSortFunc func,
gpointer data);
/* signals */
void (* row_added) (ClutterModel *model,
ClutterModelIter *iter);
void (* row_removed) (ClutterModel *model,
ClutterModelIter *iter);
void (* row_changed) (ClutterModel *model,
ClutterModelIter *iter);
void (* sort_changed) (ClutterModel *model);
void (* filter_changed) (ClutterModel *model);
/*< private >*/
/* padding for future expansion */
void (*_clutter_model_1) (void);
void (*_clutter_model_2) (void);
void (*_clutter_model_3) (void);
void (*_clutter_model_4) (void);
void (*_clutter_model_5) (void);
void (*_clutter_model_6) (void);
void (*_clutter_model_7) (void);
void (*_clutter_model_8) (void);
};
CLUTTER_DEPRECATED_FOR(g_list_model_get_type)
GType clutter_model_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_set_types (ClutterModel *model,
guint n_columns,
GType *types);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_set_names (ClutterModel *model,
guint n_columns,
const gchar * const names[]);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_append (ClutterModel *model,
...);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_appendv (ClutterModel *model,
guint n_columns,
guint *columns,
GValue *values);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_prepend (ClutterModel *model,
...);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_prependv (ClutterModel *model,
guint n_columns,
guint *columns,
GValue *values);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_insert (ClutterModel *model,
guint row,
...);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_insertv (ClutterModel *model,
guint row,
guint n_columns,
guint *columns,
GValue *values);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_insert_value (ClutterModel *model,
guint row,
guint column,
const GValue *value);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_remove (ClutterModel *model,
guint row);
CLUTTER_DEPRECATED_FOR(GListModel)
guint clutter_model_get_n_rows (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
guint clutter_model_get_n_columns (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
const gchar * clutter_model_get_column_name (ClutterModel *model,
guint column);
CLUTTER_DEPRECATED_FOR(GListModel)
GType clutter_model_get_column_type (ClutterModel *model,
guint column);
CLUTTER_DEPRECATED_FOR(GListModel)
ClutterModelIter * clutter_model_get_first_iter (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
ClutterModelIter * clutter_model_get_last_iter (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
ClutterModelIter * clutter_model_get_iter_at_row (ClutterModel *model,
guint row);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_set_sorting_column (ClutterModel *model,
gint column);
CLUTTER_DEPRECATED_FOR(GListModel)
gint clutter_model_get_sorting_column (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_foreach (ClutterModel *model,
ClutterModelForeachFunc func,
gpointer user_data);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_set_sort (ClutterModel *model,
gint column,
ClutterModelSortFunc func,
gpointer user_data,
GDestroyNotify notify);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_set_filter (ClutterModel *model,
ClutterModelFilterFunc func,
gpointer user_data,
GDestroyNotify notify);
CLUTTER_DEPRECATED_FOR(GListModel)
gboolean clutter_model_get_filter_set (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
void clutter_model_resort (ClutterModel *model);
CLUTTER_DEPRECATED_FOR(GListModel)
gboolean clutter_model_filter_row (ClutterModel *model,
guint row);
CLUTTER_DEPRECATED_FOR(GListModel)
gboolean clutter_model_filter_iter (ClutterModel *model,
ClutterModelIter *iter);
/*
* ClutterModelIter
*/
#define CLUTTER_TYPE_MODEL_ITER (clutter_model_iter_get_type ())
#define CLUTTER_MODEL_ITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MODEL_ITER, ClutterModelIter))
#define CLUTTER_MODEL_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_MODEL_ITER, ClutterModelIterClass))
#define CLUTTER_IS_MODEL_ITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MODEL_ITER))
#define CLUTTER_IS_MODEL_ITER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_MODEL_ITER))
#define CLUTTER_MODEL_ITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MODEL_ITER, ClutterModelIterClass))
/**
* ClutterModelIter:
*
* Base class for list models iters. The #ClutterModelIter structure
* contains only private data and should be manipulated using the
* provided API.
*
* Since: 0.6
*
* Deprecated: 1.24: Use custom iterators for #GListModel
*/
struct _ClutterModelIter
{
/*< private >*/
GObject parent_instance;
ClutterModelIterPrivate *priv;
};
/**
* ClutterModelIterClass:
* @get_value: Virtual function for retrieving the value at the given
* column of the row pointed by the iterator
* @set_value: Virtual function for setting the value at the given
* column of the row pointer by the iterator
* @is_last: Virtual function for knowing whether the iterator points
* at the last row in the model
* @is_first: Virtual function for knowing whether the iterator points
* at the first row in the model
* @next: Virtual function for moving the iterator to the following
* row in the model
* @prev: Virtual function for moving the iterator toe the previous
* row in the model
* @get_model: Virtual function for getting the model to which the
* iterator belongs to
* @get_row: Virtual function for getting the row to which the iterator
* points
* @copy: Virtual function for copying a #ClutterModelIter.
*
* Class for #ClutterModelIter instances.
*
* Since: 0.6
*
* Deprecated: 1.24: Use custom iterators for #GListModel
*/
struct _ClutterModelIterClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
/* vtable not signals */
void (* get_value) (ClutterModelIter *iter,
guint column,
GValue *value);
void (* set_value) (ClutterModelIter *iter,
guint column,
const GValue *value);
gboolean (* is_first) (ClutterModelIter *iter);
gboolean (* is_last) (ClutterModelIter *iter);
ClutterModelIter *(* next) (ClutterModelIter *iter);
ClutterModelIter *(* prev) (ClutterModelIter *iter);
ClutterModel * (* get_model) (ClutterModelIter *iter);
guint (* get_row) (ClutterModelIter *iter);
ClutterModelIter *(* copy) (ClutterModelIter *iter);
/*< private >*/
/* padding for future expansion */
void (*_clutter_model_iter_1) (void);
void (*_clutter_model_iter_2) (void);
void (*_clutter_model_iter_3) (void);
void (*_clutter_model_iter_4) (void);
void (*_clutter_model_iter_5) (void);
void (*_clutter_model_iter_6) (void);
void (*_clutter_model_iter_7) (void);
void (*_clutter_model_iter_8) (void);
};
CLUTTER_DEPRECATED
GType clutter_model_iter_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
void clutter_model_iter_get (ClutterModelIter *iter,
...);
CLUTTER_DEPRECATED
void clutter_model_iter_get_valist (ClutterModelIter *iter,
va_list args);
CLUTTER_DEPRECATED
void clutter_model_iter_get_value (ClutterModelIter *iter,
guint column,
GValue *value);
CLUTTER_DEPRECATED
void clutter_model_iter_set (ClutterModelIter *iter,
...);
CLUTTER_DEPRECATED
void clutter_model_iter_set_valist (ClutterModelIter *iter,
va_list args);
CLUTTER_DEPRECATED
void clutter_model_iter_set_value (ClutterModelIter *iter,
guint column,
const GValue *value);
CLUTTER_DEPRECATED
gboolean clutter_model_iter_is_first (ClutterModelIter *iter);
CLUTTER_DEPRECATED
gboolean clutter_model_iter_is_last (ClutterModelIter *iter);
CLUTTER_DEPRECATED
ClutterModelIter *clutter_model_iter_next (ClutterModelIter *iter);
CLUTTER_DEPRECATED
ClutterModelIter *clutter_model_iter_prev (ClutterModelIter *iter);
CLUTTER_DEPRECATED
ClutterModel * clutter_model_iter_get_model (ClutterModelIter *iter);
CLUTTER_DEPRECATED
guint clutter_model_iter_get_row (ClutterModelIter *iter);
CLUTTER_DEPRECATED
ClutterModelIter *clutter_model_iter_copy (ClutterModelIter *iter);
G_END_DECLS
#endif /* __CLUTTER_MODEL_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,144 +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_SCORE_H__
#define __CLUTTER_SCORE_H__
#include <clutter/clutter-timeline.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_SCORE (clutter_score_get_type ())
#define CLUTTER_SCORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_SCORE, ClutterScore))
#define CLUTTER_SCORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_SCORE, ClutterScoreClass))
#define CLUTTER_IS_SCORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_SCORE))
#define CLUTTER_IS_SCORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_SCORE))
#define CLUTTER_SCORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_SCORE, ClutterScoreClass))
typedef struct _ClutterScore ClutterScore;
typedef struct _ClutterScorePrivate ClutterScorePrivate;
typedef struct _ClutterScoreClass ClutterScoreClass;
/**
* ClutterScore:
*
* The #ClutterScore structure contains only private data
* and should be accessed using the provided API
*
* Since: 0.6
*/
struct _ClutterScore
{
/*< private >*/
GObject parent;
ClutterScorePrivate *priv;
};
/**
* ClutterScoreClass:
* @timeline_started: handler for the #ClutterScore::timeline-started signal
* @timeline_completed: handler for the #ClutterScore::timeline-completed
* signal
* @started: handler for the #ClutterScore::started signal
* @completed: handler for the #ClutterScore::completed signal
* @paused: handler for the #ClutterScore::paused signal
*
* The #ClutterScoreClass structure contains only private data
*
* Since: 0.6
*/
struct _ClutterScoreClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
void (* timeline_started) (ClutterScore *score,
ClutterTimeline *timeline);
void (* timeline_completed) (ClutterScore *score,
ClutterTimeline *timeline);
void (* started) (ClutterScore *score);
void (* completed) (ClutterScore *score);
void (* paused) (ClutterScore *score);
/*< private >*/
/* padding for future expansion */
void (*_clutter_score_1) (void);
void (*_clutter_score_2) (void);
void (*_clutter_score_3) (void);
void (*_clutter_score_4) (void);
void (*_clutter_score_5) (void);
};
CLUTTER_DEPRECATED
GType clutter_score_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
ClutterScore * clutter_score_new (void);
CLUTTER_DEPRECATED
void clutter_score_set_loop (ClutterScore *score,
gboolean loop);
CLUTTER_DEPRECATED
gboolean clutter_score_get_loop (ClutterScore *score);
CLUTTER_DEPRECATED
gulong clutter_score_append (ClutterScore *score,
ClutterTimeline *parent,
ClutterTimeline *timeline);
CLUTTER_DEPRECATED
gulong clutter_score_append_at_marker (ClutterScore *score,
ClutterTimeline *parent,
const gchar *marker_name,
ClutterTimeline *timeline);
CLUTTER_DEPRECATED
void clutter_score_remove (ClutterScore *score,
gulong id_);
CLUTTER_DEPRECATED
void clutter_score_remove_all (ClutterScore *score);
CLUTTER_DEPRECATED
ClutterTimeline *clutter_score_get_timeline (ClutterScore *score,
gulong id_);
CLUTTER_DEPRECATED
GSList * clutter_score_list_timelines (ClutterScore *score);
CLUTTER_DEPRECATED
void clutter_score_start (ClutterScore *score);
CLUTTER_DEPRECATED
void clutter_score_stop (ClutterScore *score);
CLUTTER_DEPRECATED
void clutter_score_pause (ClutterScore *score);
CLUTTER_DEPRECATED
void clutter_score_rewind (ClutterScore *score);
CLUTTER_DEPRECATED
gboolean clutter_score_is_playing (ClutterScore *score);
G_END_DECLS
#endif /* __CLUTTER_SCORE_H__ */

View File

@ -1,907 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By: Matthew Allum <mallum@openedhand.com>
* Øyvind Kolås <pippin@o-hand.com>
* Emmanuele Bassi <ebassi@linux.intel.com>
*
* Copyright (C) 2007, 2008 OpenedHand
* Copyright (C) 2009 Intel Corp
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
/**
* SECTION:clutter-shader
* @short_description: Programmable pipeline abstraction
*
* #ClutterShader is an object providing an abstraction over the
* OpenGL programmable pipeline. By using #ClutterShader<!-- -->s is
* possible to override the drawing pipeline by using small programs
* also known as "shaders".
*
* #ClutterShader is available since Clutter 0.6.
*
* #ClutterShader is deprecated since Clutter 1.8; use #ClutterShaderEffect
* in newly written code, instead.
*/
#include "clutter-build-config.h"
#include <string.h>
#include <stdlib.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include <glib.h>
#include <cogl/cogl.h>
#include "clutter-shader.h"
#include "clutter-debug.h"
#include "clutter-private.h"
/* global list of shaders */
static GList *clutter_shaders_list = NULL;
struct _ClutterShaderPrivate
{
guint compiled : 1; /* Shader is bound to the GL context */
guint is_enabled : 1;
gchar *vertex_source; /* GLSL source for vertex shader */
gchar *fragment_source; /* GLSL source for fragment shader */
CoglHandle program;
CoglHandle vertex_shader;
CoglHandle fragment_shader;
};
enum
{
PROP_0,
PROP_VERTEX_SOURCE,
PROP_FRAGMENT_SOURCE,
PROP_COMPILED,
PROP_ENABLED,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE_WITH_PRIVATE (ClutterShader, clutter_shader, G_TYPE_OBJECT)
static inline void
clutter_shader_release_internal (ClutterShader *shader)
{
ClutterShaderPrivate *priv = shader->priv;
if (!priv->compiled)
return;
g_assert (priv->program != COGL_INVALID_HANDLE);
if (priv->vertex_shader != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->vertex_shader);
if (priv->fragment_shader != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->fragment_shader);
if (priv->program != COGL_INVALID_HANDLE)
cogl_handle_unref (priv->program);
priv->vertex_shader = COGL_INVALID_HANDLE;
priv->fragment_shader = COGL_INVALID_HANDLE;
priv->program = COGL_INVALID_HANDLE;
priv->compiled = FALSE;
}
static void
clutter_shader_finalize (GObject *object)
{
ClutterShader *shader;
ClutterShaderPrivate *priv;
shader = CLUTTER_SHADER (object);
priv = shader->priv;
clutter_shaders_list = g_list_remove (clutter_shaders_list, object);
g_free (priv->fragment_source);
g_free (priv->vertex_source);
G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object);
}
static void
clutter_shader_dispose (GObject *object)
{
ClutterShader *shader = CLUTTER_SHADER (object);
clutter_shader_release_internal (shader);
G_OBJECT_CLASS (clutter_shader_parent_class)->finalize (object);
}
static void
clutter_shader_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterShader *shader = CLUTTER_SHADER(object);
switch (prop_id)
{
case PROP_VERTEX_SOURCE:
clutter_shader_set_vertex_source (shader,
g_value_get_string (value), -1);
break;
case PROP_FRAGMENT_SOURCE:
clutter_shader_set_fragment_source (shader,
g_value_get_string (value), -1);
break;
case PROP_ENABLED:
clutter_shader_set_is_enabled (shader, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_shader_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterShader *shader;
ClutterShaderPrivate *priv;
shader = CLUTTER_SHADER(object);
priv = shader->priv;
switch (prop_id)
{
case PROP_VERTEX_SOURCE:
g_value_set_string (value, priv->vertex_source);
break;
case PROP_FRAGMENT_SOURCE:
g_value_set_string (value, priv->fragment_source);
break;
case PROP_COMPILED:
g_value_set_boolean (value, priv->compiled);
break;
case PROP_ENABLED:
g_value_set_boolean (value, priv->is_enabled);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GObject *
clutter_shader_constructor (GType type,
guint n_params,
GObjectConstructParam *params)
{
GObjectClass *parent_class;
GObject *object;
parent_class = G_OBJECT_CLASS (clutter_shader_parent_class);
object = parent_class->constructor (type, n_params, params);
/* add this instance to the global list of shaders */
clutter_shaders_list = g_list_prepend (clutter_shaders_list, object);
return object;
}
static void
clutter_shader_class_init (ClutterShaderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec = NULL;
object_class->finalize = clutter_shader_finalize;
object_class->dispose = clutter_shader_dispose;
object_class->set_property = clutter_shader_set_property;
object_class->get_property = clutter_shader_get_property;
object_class->constructor = clutter_shader_constructor;
/**
* ClutterShader:vertex-source:
*
* GLSL source code for the vertex shader part of the shader
* program, if any
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
pspec = g_param_spec_string ("vertex-source",
P_("Vertex Source"),
P_("Source of vertex shader"),
NULL,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_VERTEX_SOURCE] = pspec;
g_object_class_install_property (object_class, PROP_VERTEX_SOURCE, pspec);
/**
* ClutterShader:fragment-source:
*
* GLSL source code for the fragment shader part of the shader program.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
pspec = g_param_spec_string ("fragment-source",
P_("Fragment Source"),
P_("Source of fragment shader"),
NULL,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_FRAGMENT_SOURCE] = pspec;
g_object_class_install_property (object_class, PROP_FRAGMENT_SOURCE, pspec);
/**
* ClutterShader:compiled:
*
* Whether the shader is compiled and linked, ready for use
* in the GL context.
*
* Since: 0.8
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
pspec = g_param_spec_boolean ("compiled",
P_("Compiled"),
P_("Whether the shader is compiled and linked"),
FALSE,
CLUTTER_PARAM_READABLE);
obj_props[PROP_COMPILED] = pspec;
g_object_class_install_property (object_class, PROP_COMPILED, pspec);
/**
* ClutterShader:enabled:
*
* Whether the shader is currently used in the GL rendering pipeline.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
pspec = g_param_spec_boolean ("enabled",
P_("Enabled"),
P_("Whether the shader is enabled"),
FALSE,
CLUTTER_PARAM_READWRITE);
obj_props[PROP_ENABLED] = pspec;
g_object_class_install_property (object_class, PROP_ENABLED, pspec);
}
static void
clutter_shader_init (ClutterShader *self)
{
ClutterShaderPrivate *priv;
priv = self->priv = clutter_shader_get_instance_private (self);
priv->compiled = FALSE;
priv->vertex_source = NULL;
priv->fragment_source = NULL;
priv->program = COGL_INVALID_HANDLE;
priv->vertex_shader = COGL_INVALID_HANDLE;
priv->fragment_shader = COGL_INVALID_HANDLE;
}
/**
* clutter_shader_new:
*
* Create a new #ClutterShader instance.
*
* Return value: a new #ClutterShader.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
ClutterShader *
clutter_shader_new (void)
{
return g_object_new (CLUTTER_TYPE_SHADER, NULL);
}
static inline void
clutter_shader_set_source (ClutterShader *shader,
ClutterShaderType shader_type,
const gchar *data,
gssize length)
{
ClutterShaderPrivate *priv = shader->priv;
if (length < 0)
length = strlen (data);
g_object_freeze_notify (G_OBJECT (shader));
/* release shader if bound when changing the source, the shader will
* automatically be rebound on the next use.
*/
if (clutter_shader_is_compiled (shader))
clutter_shader_release (shader);
CLUTTER_NOTE (SHADER,
"setting %s shader (len:%" G_GSSIZE_FORMAT ")",
shader_type == CLUTTER_VERTEX_SHADER ? "vertex" : "fragment",
length);
switch (shader_type)
{
case CLUTTER_FRAGMENT_SHADER:
g_free (priv->fragment_source);
priv->fragment_source = g_strndup (data, length);
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_FRAGMENT_SOURCE]);
break;
case CLUTTER_VERTEX_SHADER:
g_free (priv->vertex_source);
priv->vertex_source = g_strndup (data, length);
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_VERTEX_SOURCE]);
break;
}
g_object_thaw_notify (G_OBJECT (shader));
}
/**
* clutter_shader_set_fragment_source:
* @shader: a #ClutterShader
* @data: GLSL source code.
* @length: length of source buffer (currently ignored)
*
* Sets the GLSL source code to be used by a #ClutterShader for the fragment
* program.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
void
clutter_shader_set_fragment_source (ClutterShader *shader,
const gchar *data,
gssize length)
{
g_return_if_fail (CLUTTER_IS_SHADER (shader));
g_return_if_fail (data != NULL);
clutter_shader_set_source (shader, CLUTTER_FRAGMENT_SHADER, data, length);
}
/**
* clutter_shader_set_vertex_source:
* @shader: a #ClutterShader
* @data: GLSL source code.
* @length: length of source buffer (currently ignored)
*
* Sets the GLSL source code to be used by a #ClutterShader for the vertex
* program.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
void
clutter_shader_set_vertex_source (ClutterShader *shader,
const gchar *data,
gssize length)
{
g_return_if_fail (CLUTTER_IS_SHADER (shader));
g_return_if_fail (data != NULL);
clutter_shader_set_source (shader, CLUTTER_VERTEX_SHADER, data, length);
}
static const gchar *
clutter_shader_get_source (ClutterShader *shader,
ClutterShaderType shader_type)
{
switch (shader_type)
{
case CLUTTER_FRAGMENT_SHADER:
return shader->priv->fragment_source;
case CLUTTER_VERTEX_SHADER:
return shader->priv->vertex_source;
}
return NULL;
}
static CoglHandle
clutter_shader_get_cogl_shader (ClutterShader *shader,
ClutterShaderType shader_type)
{
switch (shader_type)
{
case CLUTTER_FRAGMENT_SHADER:
return shader->priv->fragment_shader;
case CLUTTER_VERTEX_SHADER:
return shader->priv->vertex_shader;
}
return COGL_INVALID_HANDLE;
}
static gboolean
clutter_shader_glsl_bind (ClutterShader *self,
ClutterShaderType shader_type,
GError **error)
{
ClutterShaderPrivate *priv = self->priv;
CoglHandle shader = COGL_INVALID_HANDLE;
switch (shader_type)
{
case CLUTTER_VERTEX_SHADER:
shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX);
cogl_shader_source (shader, priv->vertex_source);
priv->vertex_shader = shader;
break;
case CLUTTER_FRAGMENT_SHADER:
shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
cogl_shader_source (shader, priv->fragment_source);
priv->fragment_shader = shader;
break;
}
g_assert (shader != COGL_INVALID_HANDLE);
cogl_shader_compile (shader);
if (!cogl_shader_is_compiled (shader))
{
gchar *log_buf;
log_buf = cogl_shader_get_info_log (shader);
/* translators: the first %s is the type of the shader, either
* Vertex shader or Fragment shader; the second %s is the actual
* error as reported by COGL
*/
g_set_error (error, CLUTTER_SHADER_ERROR,
CLUTTER_SHADER_ERROR_COMPILE,
_("%s compilation failed: %s"),
shader_type == CLUTTER_VERTEX_SHADER ? _("Vertex shader")
: _("Fragment shader"),
log_buf);
g_free (log_buf);
return FALSE;
}
cogl_program_attach_shader (priv->program, shader);
return TRUE;
}
static gboolean
bind_glsl_shader (ClutterShader *self,
GError **error)
{
ClutterShaderPrivate *priv = self->priv;
GError *bind_error = NULL;
gboolean res;
priv->program = cogl_create_program ();
if (priv->vertex_source != COGL_INVALID_HANDLE)
{
res = clutter_shader_glsl_bind (self,
CLUTTER_VERTEX_SHADER,
&bind_error);
if (!res)
{
g_propagate_error (error, bind_error);
return FALSE;
}
}
if (priv->fragment_source != COGL_INVALID_HANDLE)
{
res = clutter_shader_glsl_bind (self,
CLUTTER_FRAGMENT_SHADER,
&bind_error);
if (!res)
{
g_propagate_error (error, bind_error);
return FALSE;
}
}
cogl_program_link (priv->program);
return TRUE;
}
/**
* clutter_shader_compile:
* @shader: a #ClutterShader
* @error: return location for a #GError, or %NULL
*
* Compiles and links GLSL sources set for vertex and fragment shaders for
* a #ClutterShader. If the compilation fails and a #GError return location is
* provided the error will contain the errors from the compiler, if any.
*
* Return value: returns TRUE if the shader was succesfully compiled.
*
* Since: 0.8
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
gboolean
clutter_shader_compile (ClutterShader *shader,
GError **error)
{
ClutterShaderPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE);
priv = shader->priv;
if (priv->compiled)
return priv->compiled;
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
g_set_error (error, CLUTTER_SHADER_ERROR,
CLUTTER_SHADER_ERROR_NO_GLSL,
"GLSL shaders not supported");
priv->compiled = FALSE;
return priv->compiled;
}
priv->compiled = bind_glsl_shader (shader, error);
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_COMPILED]);
return priv->compiled;
}
/**
* clutter_shader_release:
* @shader: a #ClutterShader
*
* Frees up any GL context resources held by the shader.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
void
clutter_shader_release (ClutterShader *shader)
{
g_return_if_fail (CLUTTER_IS_SHADER (shader));
clutter_shader_release_internal (shader);
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_COMPILED]);
}
/**
* clutter_shader_is_compiled:
* @shader: a #ClutterShader
*
* Checks whether @shader is is currently compiled, linked and bound
* to the GL context.
*
* Return value: %TRUE if the shader is compiled, linked and ready for use.
*
* Since: 0.8
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
gboolean
clutter_shader_is_compiled (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE);
return shader->priv->compiled;
}
/**
* clutter_shader_set_is_enabled:
* @shader: a #ClutterShader
* @enabled: The new state of the shader.
*
* Enables a shader. This function will attempt to compile and link
* the shader, if it isn't already.
*
* When @enabled is %FALSE the default state of the GL pipeline will be
* used instead.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
void
clutter_shader_set_is_enabled (ClutterShader *shader,
gboolean enabled)
{
ClutterShaderPrivate *priv;
g_return_if_fail (CLUTTER_IS_SHADER (shader));
priv = shader->priv;
if (priv->is_enabled != enabled)
{
GError *error = NULL;
gboolean res;
res = clutter_shader_compile (shader, &error);
if (!res)
{
g_warning ("Unable to bind the shader: %s",
error ? error->message : "unknown error");
if (error)
g_error_free (error);
return;
}
priv->is_enabled = enabled;
if (priv->is_enabled)
cogl_program_use (priv->program);
else
cogl_program_use (COGL_INVALID_HANDLE);
g_object_notify_by_pspec (G_OBJECT (shader), obj_props[PROP_ENABLED]);
}
}
/**
* clutter_shader_get_is_enabled:
* @shader: a #ClutterShader
*
* Checks whether @shader is enabled.
*
* Return value: %TRUE if the shader is enabled.
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
gboolean
clutter_shader_get_is_enabled (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE);
return shader->priv->is_enabled;
}
/**
* clutter_shader_set_uniform:
* @shader: a #ClutterShader.
* @name: name of uniform in GLSL shader program to set.
* @value: a #ClutterShaderFloat, #ClutterShaderInt or #ClutterShaderMatrix
* #GValue.
*
* Sets a user configurable variable in the GLSL shader programs attached to
* a #ClutterShader.
*
* Since: 1.0
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
void
clutter_shader_set_uniform (ClutterShader *shader,
const gchar *name,
const GValue *value)
{
ClutterShaderPrivate *priv;
int location = 0;
gsize size;
g_return_if_fail (CLUTTER_IS_SHADER (shader));
g_return_if_fail (name != NULL);
g_return_if_fail (value != NULL);
g_return_if_fail (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_INT (value) ||
CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value) ||
G_VALUE_HOLDS_FLOAT (value) ||
G_VALUE_HOLDS_INT (value));
priv = shader->priv;
g_return_if_fail (priv->program != COGL_INVALID_HANDLE);
location = cogl_program_get_uniform_location (priv->program, name);
if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value))
{
const float *floats;
floats = clutter_value_get_shader_float (value, &size);
cogl_program_set_uniform_float (priv->program,
location, size, 1, floats);
}
else if (CLUTTER_VALUE_HOLDS_SHADER_INT (value))
{
const int *ints;
ints = clutter_value_get_shader_int (value, &size);
cogl_program_set_uniform_int (priv->program,
location, size, 1, ints);
}
else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value))
{
const float *matrix;
matrix = clutter_value_get_shader_matrix (value, &size);
cogl_program_set_uniform_matrix (priv->program,
location, size, 1, FALSE, matrix);
}
else if (G_VALUE_HOLDS_FLOAT (value))
{
float float_val = g_value_get_float (value);
cogl_program_set_uniform_float (priv->program,
location, 1, 1, &float_val);
}
else if (G_VALUE_HOLDS_INT (value))
{
int int_val = g_value_get_int (value);
cogl_program_set_uniform_int (priv->program,
location, 1, 1, &int_val);
}
else
g_assert_not_reached ();
}
/**
* clutter_shader_get_fragment_source:
* @shader: a #ClutterShader
*
* Query the current GLSL fragment source set on @shader.
*
* Return value: the source of the fragment shader for this
* ClutterShader object or %NULL. The returned string is owned by the
* shader object and should never be modified or freed
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
const gchar *
clutter_shader_get_fragment_source (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return clutter_shader_get_source (shader, CLUTTER_FRAGMENT_SHADER);
}
/**
* clutter_shader_get_vertex_source:
* @shader: a #ClutterShader
*
* Query the current GLSL vertex source set on @shader.
*
* Return value: the source of the vertex shader for this
* ClutterShader object or %NULL. The returned string is owned by the
* shader object and should never be modified or freed
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
const gchar *
clutter_shader_get_vertex_source (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return clutter_shader_get_source (shader, CLUTTER_VERTEX_SHADER);
}
/**
* clutter_shader_get_cogl_program:
* @shader: a #ClutterShader
*
* Retrieves the underlying #CoglHandle for the shader program.
*
* Return value: (transfer none): A #CoglHandle for the shader program,
* or %NULL. The handle is owned by the #ClutterShader and it should
* not be unreferenced
*
* Since: 1.0
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
CoglHandle
clutter_shader_get_cogl_program (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return shader->priv->program;
}
/**
* clutter_shader_get_cogl_fragment_shader:
* @shader: a #ClutterShader
*
* Retrieves the underlying #CoglHandle for the fragment shader.
*
* Return value: (transfer none): A #CoglHandle for the fragment
* shader, or %NULL. The handle is owned by the #ClutterShader
* and it should not be unreferenced
*
* Since: 1.0
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
CoglHandle
clutter_shader_get_cogl_fragment_shader (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return clutter_shader_get_cogl_shader (shader, CLUTTER_FRAGMENT_SHADER);
}
/**
* clutter_shader_get_cogl_vertex_shader:
* @shader: a #ClutterShader
*
* Retrieves the underlying #CoglHandle for the vertex shader.
*
* Return value: (transfer none): A #CoglHandle for the vertex
* shader, or %NULL. The handle is owned by the #ClutterShader
* and it should not be unreferenced
*
* Since: 1.0
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead.
*/
CoglHandle
clutter_shader_get_cogl_vertex_shader (ClutterShader *shader)
{
g_return_val_if_fail (CLUTTER_IS_SHADER (shader), NULL);
return clutter_shader_get_cogl_shader (shader, CLUTTER_VERTEX_SHADER);
}
GQuark
clutter_shader_error_quark (void)
{
return g_quark_from_static_string ("clutter-shader-error");
}

View File

@ -1,182 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Øyvind Kolås <pippin@o-hand.com>
*
* Copyright (C) 2007 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_SHADER_H__
#define __CLUTTER_SHADER_H__
#include <clutter/clutter-types.h>
#include <clutter/clutter-shader-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_SHADER (clutter_shader_get_type ())
#define CLUTTER_SHADER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CLUTTER_TYPE_SHADER, ClutterShader))
#define CLUTTER_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CLUTTER_TYPE_SHADER, ClutterShaderClass))
#define CLUTTER_IS_SHADER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CLUTTER_TYPE_SHADER))
#define CLUTTER_IS_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CLUTTER_TYPE_SHADER))
#define CLUTTER_SHADER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CLUTTER_TYPE_SHADER, ClutterShaderClass))
/**
* CLUTTER_SHADER_ERROR:
*
* Error domain for #ClutterShader errors
*
* Since: 0.6
*
* Deprecated: 1.8
*/
#define CLUTTER_SHADER_ERROR (clutter_shader_error_quark ())
/**
* ClutterShaderError:
* @CLUTTER_SHADER_ERROR_NO_ASM: No ASM shaders support
* @CLUTTER_SHADER_ERROR_NO_GLSL: No GLSL shaders support
* @CLUTTER_SHADER_ERROR_COMPILE: Compilation error
*
* #ClutterShader error enumeration
*
* Since: 0.6
*
* Deprecated: 1.8
*/
typedef enum {
CLUTTER_SHADER_ERROR_NO_ASM,
CLUTTER_SHADER_ERROR_NO_GLSL,
CLUTTER_SHADER_ERROR_COMPILE
} ClutterShaderError;
typedef struct _ClutterShaderPrivate ClutterShaderPrivate;
typedef struct _ClutterShaderClass ClutterShaderClass;
/**
* ClutterShader:
*
* The #ClutterShader structure contains only private data
* and should be accessed using the provided API
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffect instead
*/
struct _ClutterShader
{
/*< private >*/
GObject parent;
ClutterShaderPrivate *priv;
};
/**
* ClutterShaderClass:
*
* The #ClutterShaderClass structure contains only private data
*
* Since: 0.6
*
* Deprecated: 1.8: Use #ClutterShaderEffectClass instead
*/
struct _ClutterShaderClass
{
/*< private >*/
GObjectClass parent_class;
};
CLUTTER_DEPRECATED
GQuark clutter_shader_error_quark (void);
CLUTTER_DEPRECATED
GType clutter_shader_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
ClutterShader * clutter_shader_new (void);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
void clutter_shader_set_is_enabled (ClutterShader *shader,
gboolean enabled);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
gboolean clutter_shader_get_is_enabled (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
gboolean clutter_shader_compile (ClutterShader *shader,
GError **error);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
void clutter_shader_release (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
gboolean clutter_shader_is_compiled (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
void clutter_shader_set_vertex_source (ClutterShader *shader,
const gchar *data,
gssize length);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
void clutter_shader_set_fragment_source (ClutterShader *shader,
const gchar *data,
gssize length);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
const gchar * clutter_shader_get_vertex_source (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
const gchar * clutter_shader_get_fragment_source (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
void clutter_shader_set_uniform (ClutterShader *shader,
const gchar *name,
const GValue *value);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
CoglHandle clutter_shader_get_cogl_program (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
CoglHandle clutter_shader_get_cogl_fragment_shader (ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(ClutterShaderEffect)
CoglHandle clutter_shader_get_cogl_vertex_shader (ClutterShader *shader);
/* ClutterActor methods */
CLUTTER_DEPRECATED_FOR(clutter_actor_add_effect)
gboolean clutter_actor_set_shader (ClutterActor *self,
ClutterShader *shader);
CLUTTER_DEPRECATED_FOR(clutter_actor_get_effect)
ClutterShader * clutter_actor_get_shader (ClutterActor *self);
CLUTTER_DEPRECATED_FOR(clutter_shader_effect_set_uniform_value)
void clutter_actor_set_shader_param (ClutterActor *self,
const gchar *param,
const GValue *value);
CLUTTER_DEPRECATED_FOR(clutter_shader_effect_set_uniform)
void clutter_actor_set_shader_param_int (ClutterActor *self,
const gchar *param,
gint value);
CLUTTER_DEPRECATED_FOR(clutter_shader_effect_set_uniform)
void clutter_actor_set_shader_param_float (ClutterActor *self,
const gchar *param,
gfloat value);
G_END_DECLS
#endif /* __CLUTTER_SHADER_H__ */

View File

@ -131,7 +131,6 @@
* "source" : "source-state",
* "target" : "target-state",
* "duration" : milliseconds,
* "animator" : "animator-definition"
* },
* ...
* ]
@ -142,7 +141,7 @@
* as clutter_state_set_key() function arguments.
*
* The source and target values control the source and target state of the
* transition. The key and animator properties are mutually exclusive.
* transition.
*
* The pre-delay and post-delay values are optional.
*
@ -189,7 +188,6 @@
#include "clutter-alpha.h"
#include "clutter-animatable.h"
#include "clutter-animator.h"
#include "clutter-enum-types.h"
#include "clutter-interval.h"
#include "clutter-marshal.h"
@ -197,11 +195,6 @@
#include "clutter-scriptable.h"
#include "clutter-script-private.h"
typedef struct StateAnimator {
const gchar *source_state_name; /* interned string identifying entry */
ClutterAnimator *animator; /* pointer to animator itself */
} StateAnimator;
typedef struct State
{
const gchar *name; /* interned string for this state name */
@ -209,8 +202,6 @@ typedef struct State
names */
GList *keys; /* list of all keys pertaining to transitions
from other states to this one */
GArray *animators; /* list of animators for transitioning from
* specific source states */
ClutterState *clutter_state; /* the ClutterState object this state belongs to
*/
} State;
@ -227,8 +218,6 @@ struct _ClutterStatePrivate
State *source_state; /* current source_state */
const gchar *target_state_name; /* current target state */
State *target_state; /* target state name */
ClutterAnimator *current_animator; /* !NULL if the current transition is
overriden by an animator */
};
#define SLAVE_TIMELINE_LENGTH 10000
@ -496,7 +485,6 @@ state_free (gpointer data)
state->keys = g_list_remove (state->keys, state->keys->data))
clutter_state_key_free (state->keys->data);
g_array_free (state->animators, TRUE);
g_hash_table_destroy (state->durations);
g_free (state);
}
@ -510,7 +498,6 @@ state_new (ClutterState *clutter_state,
state = g_new0 (State, 1);
state->clutter_state = clutter_state;
state->name = name;
state->animators = g_array_new (TRUE, TRUE, sizeof (StateAnimator));
state->durations = g_hash_table_new (g_direct_hash, g_direct_equal);
return state;
@ -533,14 +520,6 @@ static void
clutter_state_completed (ClutterTimeline *timeline,
ClutterState *state)
{
ClutterStatePrivate *priv = state->priv;
if (priv->current_animator)
{
clutter_animator_set_timeline (priv->current_animator, NULL);
priv->current_animator = NULL;
}
g_signal_emit (state, state_signals[COMPLETED], 0);
}
@ -556,9 +535,6 @@ clutter_state_new_frame (ClutterTimeline *timeline,
GObject *curobj = NULL;
gboolean found_specific = FALSE;
if (priv->current_animator)
return;
progress = clutter_timeline_get_progress (timeline);
for (k = priv->target_state->keys; k; k = k->next)
@ -649,7 +625,6 @@ clutter_state_change (ClutterState *state,
gboolean animate)
{
ClutterStatePrivate *priv;
ClutterAnimator *animator;
State *new_state;
guint duration;
GList *k;
@ -673,12 +648,6 @@ clutter_state_change (ClutterState *state,
clutter_timeline_stop (priv->timeline);
clutter_timeline_rewind (priv->timeline);
if (priv->current_animator)
{
clutter_animator_set_timeline (priv->current_animator, NULL);
priv->current_animator = NULL;
}
return NULL;
}
@ -694,12 +663,6 @@ clutter_state_change (ClutterState *state,
return priv->timeline;
}
if (priv->current_animator != NULL)
{
clutter_animator_set_timeline (priv->current_animator, NULL);
priv->current_animator = NULL;
}
priv->source_state_name = priv->target_state_name;
priv->target_state_name = target_state_name;
@ -718,55 +681,37 @@ clutter_state_change (ClutterState *state,
return NULL;
}
animator = clutter_state_get_animator (state,
priv->source_state_name,
priv->target_state_name);
priv->target_state = new_state;
if (animator == NULL && new_state->keys == NULL)
animator = clutter_state_get_animator (state, NULL,
priv->target_state_name);
if (animator != NULL)
for (k = new_state->keys; k != NULL; k = k->next)
{
/* we've got an animator overriding the tweened animation */
priv->current_animator = animator;
clutter_animator_set_timeline (animator, priv->timeline);
}
else
{
for (k = new_state->keys; k != NULL; k = k->next)
ClutterStateKey *key = k->data;
GValue initial = G_VALUE_INIT;
/* Reset the pre-pre-delay - this is only used for setting keys
* during transitions.
*/
key->pre_pre_delay = 0;
g_value_init (&initial, clutter_interval_get_value_type (key->interval));
if (key->is_animatable)
{
ClutterStateKey *key = k->data;
GValue initial = G_VALUE_INIT;
ClutterAnimatable *animatable;
/* Reset the pre-pre-delay - this is only used for setting keys
* during transitions.
*/
key->pre_pre_delay = 0;
g_value_init (&initial, clutter_interval_get_value_type (key->interval));
if (key->is_animatable)
{
ClutterAnimatable *animatable;
animatable = CLUTTER_ANIMATABLE (key->object);
clutter_animatable_get_initial_state (animatable,
key->property_name,
&initial);
}
else
g_object_get_property (key->object, key->property_name, &initial);
if (clutter_alpha_get_mode (key->alpha) != key->mode)
clutter_alpha_set_mode (key->alpha, key->mode);
clutter_interval_set_initial_value (key->interval, &initial);
clutter_interval_set_final_value (key->interval, &key->value);
g_value_unset (&initial);
animatable = CLUTTER_ANIMATABLE (key->object);
clutter_animatable_get_initial_state (animatable,
key->property_name,
&initial);
}
else
g_object_get_property (key->object, key->property_name, &initial);
if (clutter_alpha_get_mode (key->alpha) != key->mode)
clutter_alpha_set_mode (key->alpha, key->mode);
clutter_interval_set_initial_value (key->interval, &initial);
clutter_interval_set_final_value (key->interval, &key->value);
g_value_unset (&initial);
}
if (!animate)
@ -1549,126 +1494,6 @@ clutter_state_init (ClutterState *self)
}
/**
* clutter_state_get_animator:
* @state: a #ClutterState instance.
* @source_state_name: the name of a source state
* @target_state_name: the name of a target state
*
* Retrieves the #ClutterAnimator that is being used for transitioning
* between the two states, if any has been set
*
* Return value: (transfer none): a #ClutterAnimator instance, or %NULL
*
* Since: 1.4
* Deprecated: 1.12: Use #ClutterKeyframeTransition and
* #ClutterTransitionGroup instead
*/
ClutterAnimator *
clutter_state_get_animator (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name)
{
State *target_state;
guint i;
g_return_val_if_fail (CLUTTER_IS_STATE (state), NULL);
source_state_name = g_intern_string (source_state_name);
if (source_state_name == g_intern_static_string (""))
source_state_name = NULL;
target_state_name = g_intern_string (target_state_name);
target_state = clutter_state_fetch_state (state, target_state_name, FALSE);
if (target_state == NULL)
return NULL;
for (i = 0; i < target_state->animators->len; i++)
{
const StateAnimator *animator;
animator = &g_array_index (target_state->animators, StateAnimator, i);
if (animator->source_state_name == source_state_name)
return animator->animator;
}
return NULL;
}
/**
* clutter_state_set_animator:
* @state: a #ClutterState instance.
* @source_state_name: the name of a source state
* @target_state_name: the name of a target state
* @animator: (allow-none): a #ClutterAnimator instance, or %NULL to
* unset an existing #ClutterAnimator
*
* Specifies a #ClutterAnimator to be used when transitioning between
* the two named states.
*
* The @animator allows specifying a transition between the state that is
* more elaborate than the basic transitions allowed by the tweening of
* properties defined in the #ClutterState keys.
*
* If @animator is %NULL it will unset an existing animator.
*
* #ClutterState will take a reference on the passed @animator, if any
*
* Since: 1.4
* Deprecated: 1.12: Use #ClutterKeyframeTransition and
* #ClutterTransitionGroup instead
*/
void
clutter_state_set_animator (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name,
ClutterAnimator *animator)
{
State *target_state;
guint i;
g_return_if_fail (CLUTTER_IS_STATE (state));
source_state_name = g_intern_string (source_state_name);
target_state_name = g_intern_string (target_state_name);
target_state = clutter_state_fetch_state (state, target_state_name, TRUE);
if (target_state == NULL)
return;
for (i = 0; target_state->animators->len; i++)
{
StateAnimator *a;
a = &g_array_index (target_state->animators, StateAnimator, i);
if (a->source_state_name == source_state_name)
{
g_object_unref (a->animator);
if (animator != NULL)
a->animator = g_object_ref (animator);
else
{
/* remove the matched animator if passed NULL */
g_array_remove_index (target_state->animators, i);
}
return;
}
}
if (animator != NULL)
{
StateAnimator state_animator = {
source_state_name,
g_object_ref (animator)
};
g_array_append_val (target_state->animators, state_animator);
}
}
static gpointer
clutter_state_key_copy (gpointer boxed)
{
@ -2107,12 +1932,10 @@ parse_state_transition (JsonArray *array,
if (!json_object_has_member (object, "source") ||
!json_object_has_member (object, "target") ||
!(json_object_has_member (object, "keys") ||
json_object_has_member (object, "animator")))
!(json_object_has_member (object, "keys")))
{
g_warning ("The transition description at index %d is missing one "
"of the mandatory members: source, target and keys or "
"animator", index_);
"of the mandatory members: source, target and keys", index_);
return;
}
@ -2131,29 +1954,11 @@ parse_state_transition (JsonArray *array,
duration);
}
if (json_object_has_member (object, "animator"))
{
const gchar *id_ = json_object_get_string_member (object, "animator");
GObject *animator;
animator = clutter_script_get_object (clos->script, id_);
if (animator == NULL)
{
g_warning ("No object with id '%s' has been defined.", id_);
return;
}
clutter_state_set_animator (clos->state,
source_name,
target_name,
CLUTTER_ANIMATOR (animator));
}
if (!json_object_has_member (object, "keys"))
return;
keys = json_object_get_array_member (object, "keys");
if (keys == NULL && !json_object_has_member (object, "animator"))
if (keys == NULL)
{
g_warning ("The transition description at index %d has an invalid "
"key member of type '%s' when an array was expected.",

View File

@ -145,15 +145,6 @@ void clutter_state_remove_key (ClutterState *state,
CLUTTER_DEPRECATED
ClutterTimeline * clutter_state_get_timeline (ClutterState *state);
CLUTTER_DEPRECATED
void clutter_state_set_animator (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name,
ClutterAnimator *animator);
CLUTTER_DEPRECATED
ClutterAnimator * clutter_state_get_animator (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name);
CLUTTER_DEPRECATED
const gchar * clutter_state_get_state (ClutterState *state);
/*

View File

@ -64,9 +64,7 @@
#include "clutter-stage-private.h"
#include "clutter-backend.h"
#include "deprecated/clutter-shader.h"
#include "deprecated/clutter-texture.h"
#include "deprecated/clutter-util.h"
typedef struct _ClutterTextureAsyncData ClutterTextureAsyncData;
@ -480,22 +478,10 @@ update_fbo (ClutterActor *self)
{
ClutterTexture *texture = CLUTTER_TEXTURE (self);
ClutterTexturePrivate *priv = texture->priv;
ClutterActor *head;
ClutterShader *shader = NULL;
ClutterActor *stage = NULL;
CoglMatrix projection;
CoglColor transparent_col;
head = _clutter_context_peek_shader_stack ();
if (head != NULL)
shader = clutter_actor_get_shader (head);
/* Temporarily turn off the shader on the top of the context's
* shader stack, to restore the GL pipeline to it's natural state.
*/
if (shader != NULL)
clutter_shader_set_is_enabled (shader, FALSE);
/* Redirect drawing to the fbo */
cogl_push_framebuffer (priv->fbo_handle);
@ -554,10 +540,6 @@ update_fbo (ClutterActor *self)
/* Restore drawing to the previous framebuffer */
cogl_pop_framebuffer ();
/* If there is a shader on top of the shader stack, turn it back on. */
if (shader != NULL)
clutter_shader_set_is_enabled (shader, TRUE);
}
static void

View File

@ -1,140 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Neil Roberts <neil@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/>.
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
/* This file contains the common code to check whether an interval has
expired used in clutter-frame-source and clutter-timeout-pool. */
#include "clutter-timeout-interval.h"
void
_clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
guint fps)
{
#if GLIB_CHECK_VERSION (2, 27, 3)
interval->start_time = g_get_monotonic_time () / 1000;
#else
{
GTimeVal start_time;
g_get_current_time (&start_time);
interval->start_time = start_time.tv_sec * 1000
+ start_time.tv_usec / 1000;
}
#endif
interval->fps = fps;
interval->frame_count = 0;
}
static gint64
_clutter_timeout_interval_get_ticks (gint64 current_time,
ClutterTimeoutInterval *interval)
{
return MAX (current_time - interval->start_time, 0);
}
gboolean
_clutter_timeout_interval_prepare (gint64 current_time,
ClutterTimeoutInterval *interval,
gint *delay)
{
gint elapsed_time, new_frame_num;
elapsed_time = _clutter_timeout_interval_get_ticks (current_time, interval);
new_frame_num = elapsed_time * interval->fps / 1000;
/* If time has gone backwards or the time since the last frame is
greater than the two frames worth then reset the time and do a
frame now */
if (new_frame_num < interval->frame_count ||
new_frame_num - interval->frame_count > 2)
{
/* Get the frame time rounded up to the nearest ms */
guint frame_time = (1000 + interval->fps - 1) / interval->fps;
/* Reset the start time */
interval->start_time = current_time;
/* Move the start time as if one whole frame has elapsed */
interval->start_time -= frame_time;
interval->frame_count = 0;
if (delay)
*delay = 0;
return TRUE;
}
else if (new_frame_num > interval->frame_count)
{
if (delay)
*delay = 0;
return TRUE;
}
else
{
if (delay)
*delay = ((interval->frame_count + 1) * 1000 / interval->fps
- elapsed_time);
return FALSE;
}
}
gboolean
_clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
GSourceFunc callback,
gpointer user_data)
{
if ((* callback) (user_data))
{
interval->frame_count++;
return TRUE;
}
return FALSE;
}
gint
_clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
const ClutterTimeoutInterval *b)
{
guint a_delay = 1000 / a->fps;
guint b_delay = 1000 / b->fps;
gint64 b_difference;
gint comparison;
b_difference = a->start_time - b->start_time;
comparison = ((gint) ((a->frame_count + 1) * a_delay)
- (gint) ((b->frame_count + 1) * b_delay + b_difference));
return (comparison < 0 ? -1
: comparison > 0 ? 1
: 0);
}

View File

@ -1,58 +0,0 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Neil Roberts <neil@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_TIMEOUT_INTERVAL_H__
#define __CLUTTER_TIMEOUT_INTERVAL_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct _ClutterTimeoutInterval ClutterTimeoutInterval;
struct _ClutterTimeoutInterval
{
/* milliseconds */
gint64 start_time;
guint frame_count;
guint fps;
};
void _clutter_timeout_interval_init (ClutterTimeoutInterval *interval,
guint fps);
gboolean _clutter_timeout_interval_prepare (gint64 current_time,
ClutterTimeoutInterval *interval,
gint *delay);
gboolean _clutter_timeout_interval_dispatch (ClutterTimeoutInterval *interval,
GSourceFunc callback,
gpointer user_data);
gint _clutter_timeout_interval_compare_expiration (const ClutterTimeoutInterval *a,
const ClutterTimeoutInterval *b);
G_END_DECLS
#endif /* __CLUTTER_TIMEOUT_INTERVAL_H__ */

View File

@ -1,498 +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/>.
*
*
*
* ClutterTimeoutPool: pool of timeout functions using the same slice of
* the GLib main loop
*
* Author: Emmanuele Bassi <ebassi@openedhand.com>
*
* Based on similar code by Tristan van Berkom
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-main.h"
#include "clutter-timeout-pool.h"
#include "clutter-debug.h"
#include "clutter-timeout-interval.h"
typedef struct _ClutterTimeout ClutterTimeout;
typedef enum {
CLUTTER_TIMEOUT_NONE = 0,
CLUTTER_TIMEOUT_READY = 1 << 1
} ClutterTimeoutFlags;
struct _ClutterTimeout
{
guint id;
ClutterTimeoutFlags flags;
gint refcount;
ClutterTimeoutInterval interval;
GSourceFunc func;
gpointer data;
GDestroyNotify notify;
};
struct _ClutterTimeoutPool
{
GSource source;
guint next_id;
GList *timeouts;
GList *dispatched_timeouts;
gint ready;
guint id;
};
#define TIMEOUT_READY(timeout) (timeout->flags & CLUTTER_TIMEOUT_READY)
static gboolean clutter_timeout_pool_prepare (GSource *source,
gint *next_timeout);
static gboolean clutter_timeout_pool_check (GSource *source);
static gboolean clutter_timeout_pool_dispatch (GSource *source,
GSourceFunc callback,
gpointer data);
static void clutter_timeout_pool_finalize (GSource *source);
static GSourceFuncs clutter_timeout_pool_funcs =
{
clutter_timeout_pool_prepare,
clutter_timeout_pool_check,
clutter_timeout_pool_dispatch,
clutter_timeout_pool_finalize
};
static gint
clutter_timeout_sort (gconstpointer a,
gconstpointer b)
{
const ClutterTimeout *t_a = a;
const ClutterTimeout *t_b = b;
/* Keep 'ready' timeouts at the front */
if (TIMEOUT_READY (t_a))
return -1;
if (TIMEOUT_READY (t_b))
return 1;
return _clutter_timeout_interval_compare_expiration (&t_a->interval,
&t_b->interval);
}
static gint
clutter_timeout_find_by_id (gconstpointer a,
gconstpointer b)
{
const ClutterTimeout *t_a = a;
return t_a->id == GPOINTER_TO_UINT (b) ? 0 : 1;
}
static ClutterTimeout *
clutter_timeout_new (guint fps)
{
ClutterTimeout *timeout;
timeout = g_slice_new0 (ClutterTimeout);
_clutter_timeout_interval_init (&timeout->interval, fps);
timeout->flags = CLUTTER_TIMEOUT_NONE;
timeout->refcount = 1;
return timeout;
}
static gboolean
clutter_timeout_prepare (ClutterTimeoutPool *pool,
ClutterTimeout *timeout,
gint *next_timeout)
{
GSource *source = (GSource *) pool;
gint64 now;
#if GLIB_CHECK_VERSION (2, 27, 3)
now = g_source_get_time (source) / 1000;
#else
{
GTimeVal source_time;
g_source_get_current_time (source, &source_time);
now = source_time.tv_sec * 1000 + source_time.tv_usec / 1000;
}
#endif
return _clutter_timeout_interval_prepare (now,
&timeout->interval,
next_timeout);
}
/* ref and unref are always called under the main Clutter lock, so there
* is not need for us to use g_atomic_int_* API.
*/
static ClutterTimeout *
clutter_timeout_ref (ClutterTimeout *timeout)
{
g_return_val_if_fail (timeout != NULL, timeout);
g_return_val_if_fail (timeout->refcount > 0, timeout);
timeout->refcount += 1;
return timeout;
}
static void
clutter_timeout_unref (ClutterTimeout *timeout)
{
g_return_if_fail (timeout != NULL);
g_return_if_fail (timeout->refcount > 0);
timeout->refcount -= 1;
if (timeout->refcount == 0)
{
if (timeout->notify)
timeout->notify (timeout->data);
g_slice_free (ClutterTimeout, timeout);
}
}
static void
clutter_timeout_free (ClutterTimeout *timeout)
{
if (G_LIKELY (timeout))
{
if (timeout->notify)
timeout->notify (timeout->data);
g_slice_free (ClutterTimeout, timeout);
}
}
static gboolean
clutter_timeout_pool_prepare (GSource *source,
gint *next_timeout)
{
ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source;
GList *l = pool->timeouts;
/* the pool is ready if the first timeout is ready */
if (l && l->data)
{
ClutterTimeout *timeout = l->data;
return clutter_timeout_prepare (pool, timeout, next_timeout);
}
else
{
*next_timeout = -1;
return FALSE;
}
}
static gboolean
clutter_timeout_pool_check (GSource *source)
{
ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source;
GList *l;
clutter_threads_enter ();
for (l = pool->timeouts; l; l = l->next)
{
ClutterTimeout *timeout = l->data;
/* since the timeouts are sorted by expiration, as soon
* as we get a check returning FALSE we know that the
* following timeouts are not expiring, so we break as
* soon as possible
*/
if (clutter_timeout_prepare (pool, timeout, NULL))
{
timeout->flags |= CLUTTER_TIMEOUT_READY;
pool->ready += 1;
}
else
break;
}
clutter_threads_leave ();
return (pool->ready > 0);
}
static gboolean
clutter_timeout_pool_dispatch (GSource *source,
GSourceFunc func,
gpointer data)
{
ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source;
GList *dispatched_timeouts;
/* the main loop might have predicted this, so we repeat the
* check for ready timeouts.
*/
if (!pool->ready)
clutter_timeout_pool_check (source);
clutter_threads_enter ();
/* Iterate by moving the actual start of the list along so that it
* can cope with adds and removes while a timeout is being dispatched
*/
while (pool->timeouts && pool->timeouts->data && pool->ready-- > 0)
{
ClutterTimeout *timeout = pool->timeouts->data;
GList *l;
/* One of the ready timeouts may have been removed during dispatch,
* in which case pool->ready will be wrong, but the ready timeouts
* are always kept at the start of the list so we can stop once
* we've reached the first non-ready timeout
*/
if (!(TIMEOUT_READY (timeout)))
break;
/* Add a reference to the timeout so it can't disappear
* while it's being dispatched
*/
clutter_timeout_ref (timeout);
timeout->flags &= ~CLUTTER_TIMEOUT_READY;
/* Move the list node to a list of dispatched timeouts */
l = pool->timeouts;
if (l->next)
l->next->prev = NULL;
pool->timeouts = l->next;
if (pool->dispatched_timeouts)
pool->dispatched_timeouts->prev = l;
l->prev = NULL;
l->next = pool->dispatched_timeouts;
pool->dispatched_timeouts = l;
if (!_clutter_timeout_interval_dispatch (&timeout->interval,
timeout->func, timeout->data))
{
/* The timeout may have already been removed, but nothing
* can be added to the dispatched_timeout list except in this
* function so it will always either be at the head of the
* dispatched list or have been removed
*/
if (pool->dispatched_timeouts &&
pool->dispatched_timeouts->data == timeout)
{
pool->dispatched_timeouts =
g_list_delete_link (pool->dispatched_timeouts,
pool->dispatched_timeouts);
/* Remove the reference that was held by it being in the list */
clutter_timeout_unref (timeout);
}
}
clutter_timeout_unref (timeout);
}
/* Re-insert the dispatched timeouts in sorted order */
dispatched_timeouts = pool->dispatched_timeouts;
while (dispatched_timeouts)
{
ClutterTimeout *timeout = dispatched_timeouts->data;
GList *next = dispatched_timeouts->next;
if (timeout)
pool->timeouts = g_list_insert_sorted (pool->timeouts, timeout,
clutter_timeout_sort);
dispatched_timeouts = next;
}
g_list_free (pool->dispatched_timeouts);
pool->dispatched_timeouts = NULL;
pool->ready = 0;
clutter_threads_leave ();
return TRUE;
}
static void
clutter_timeout_pool_finalize (GSource *source)
{
ClutterTimeoutPool *pool = (ClutterTimeoutPool *) source;
/* force destruction */
g_list_foreach (pool->timeouts, (GFunc) clutter_timeout_free, NULL);
g_list_free (pool->timeouts);
}
/**
* clutter_timeout_pool_new:
* @priority: the priority of the timeout pool. Typically this will
* be #G_PRIORITY_DEFAULT
*
* Creates a new timeout pool source. A timeout pool should be used when
* multiple timeout functions, running at the same priority, are needed and
* the g_timeout_add() API might lead to starvation of the time slice of
* the main loop. A timeout pool allocates a single time slice of the main
* loop and runs every timeout function inside it. The timeout pool is
* always sorted, so that the extraction of the next timeout function is
* a constant time operation.
*
* Return value: the newly created #ClutterTimeoutPool. The created pool
* is owned by the GLib default context and will be automatically
* destroyed when the context is destroyed. It is possible to force
* the destruction of the timeout pool using g_source_destroy()
*
* Since: 0.4
*
* Deprecated: 1.6: There is no direct replacement for this API
*/
ClutterTimeoutPool *
clutter_timeout_pool_new (gint priority)
{
ClutterTimeoutPool *pool;
GSource *source;
source = g_source_new (&clutter_timeout_pool_funcs,
sizeof (ClutterTimeoutPool));
if (!source)
return NULL;
g_source_set_name (source, "Clutter timeout pool");
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority (source, priority);
pool = (ClutterTimeoutPool *) source;
pool->next_id = 1;
pool->id = g_source_attach (source, NULL);
/* let the default GLib context manage the pool */
g_source_unref (source);
return pool;
}
/**
* clutter_timeout_pool_add:
* @pool: a #ClutterTimeoutPool
* @fps: the time between calls to the function, in frames per second
* @func: function to call
* @data: (closure): data to pass to the function, or %NULL
* @notify: function to call when the timeout is removed, or %NULL
*
* Sets a function to be called at regular intervals, and puts it inside
* the @pool. The function is repeatedly called until it returns %FALSE,
* at which point the timeout is automatically destroyed and the function
* won't be called again. If @notify is not %NULL, the @notify function
* will be called. The first call to @func will be at the end of @interval.
*
* Since Clutter 0.8 this will try to compensate for delays. For
* example, if @func takes half the interval time to execute then the
* function will be called again half the interval time after it
* finished. Before version 0.8 it would not fire until a full
* interval after the function completes so the delay between calls
* would be @interval * 1.5. This function does not however try to
* invoke the function multiple times to catch up missing frames if
* @func takes more than @interval ms to execute.
*
* Return value: the ID (greater than 0) of the timeout inside the pool.
* Use clutter_timeout_pool_remove() to stop the timeout.
*
* Since: 0.4
*
* Deprecated: 1.6: There is no direct replacement for this API
*/
guint
clutter_timeout_pool_add (ClutterTimeoutPool *pool,
guint fps,
GSourceFunc func,
gpointer data,
GDestroyNotify notify)
{
ClutterTimeout *timeout;
guint retval = 0;
timeout = clutter_timeout_new (fps);
retval = timeout->id = pool->next_id++;
timeout->func = func;
timeout->data = data;
timeout->notify = notify;
pool->timeouts = g_list_insert_sorted (pool->timeouts, timeout,
clutter_timeout_sort);
return retval;
}
/**
* clutter_timeout_pool_remove:
* @pool: a #ClutterTimeoutPool
* @id_: the id of the timeout to remove
*
* Removes a timeout function with @id_ from the timeout pool. The id
* is the same returned when adding a function to the timeout pool with
* clutter_timeout_pool_add().
*
* Since: 0.4
*
* Deprecated: 1.6: There is no direct replacement for this API
*/
void
clutter_timeout_pool_remove (ClutterTimeoutPool *pool,
guint id_)
{
GList *l;
if ((l = g_list_find_custom (pool->timeouts, GUINT_TO_POINTER (id_),
clutter_timeout_find_by_id)))
{
clutter_timeout_unref (l->data);
pool->timeouts = g_list_delete_link (pool->timeouts, l);
}
else if ((l = g_list_find_custom (pool->dispatched_timeouts,
GUINT_TO_POINTER (id_),
clutter_timeout_find_by_id)))
{
clutter_timeout_unref (l->data);
pool->dispatched_timeouts =
g_list_delete_link (pool->dispatched_timeouts, l);
}
}

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