Compare commits

..

2 Commits

Author SHA1 Message Date
Carlos Garnacho
6dda417773 backends/input-mapper: Add some g_debug() traces to MetaInputMapper
Add some debug statements to mapping_helper_apply(), enough to work out
the heuristic decisions that were taken.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1202
2020-04-16 16:31:45 +02:00
Carlos Garnacho
d4bc355ee9 backends/input-mapper: Implement score mechanism to assign the most relevant output
We used to pick the "best" output for each builtin/size/edid categories,
and then pick the "best" (in that order) of those for each input device.
This is most often enough, but is prone to wrong results in some corner
cases (eg. 2 outputs with the exact same dimensions).

Change this to a score mechanism that doesn't leave outputs out. The
weights are the same, but the score is accumulated if an output matches
multiple categories. All outputs are evaluated and sorted by score, and
input devices with the best matches are applied first (as they already
did).

This should break the tie if eg. there's 2 outputs with similar dimensions,
but one of them has some EDID match in addition. The output with multiple
matches will score higher up, while it might have been entirely discarded
with the previous implementation.

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

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1202
2020-04-16 16:31:14 +02:00
276 changed files with 13179 additions and 11547 deletions

View File

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

View File

@@ -16,7 +16,7 @@ RUN dnf -y update && dnf -y upgrade && \
# For running unit tests
dnf install -y xorg-x11-server-Xvfb mesa-dri-drivers dbus dbus-x11 \
'*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center gcovr \
'*/xvfb-run' gdm-lib accountsservice-libs gnome-control-center \
--setopt=install_weak_deps=False && \
# GNOME Shell

33
NEWS
View File

@@ -1,36 +1,3 @@
3.37.1
======
* Fix screencasting non-maximized windows [Jonas Å.; !1174]
* Make window-aliveness checks less aggressive [Jonas Å.; !1182]
* Fix stylus coordinates when using screen rotation [Jonas T.; #1118]
* Preserve keyboard state on VT switch [Olivier; !1185]
* Remove Clutter's drag and drop actions [Jonas D.; !789]
* Cancel clicks/gestures actions on disable [Georges; !1188]
* Fix various clipboard issues [Carlos; !1186, !1198, !1203, !1204, !1206]
* Fix trackball button scrolling [Phillip; #1120]
* Fix tiled monitor support [Jonas; !1199]
* Support unredirecting fullscreen wayland surfaces [Jonas Å.; !798]
* Support area screencasts [Jonas Å.; !1207]
* Synchronize shadows to server-side decorations [Olivier; !1214]
* Allow inhibiting remote access [Jonas Å.; !1212]
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
* Fixed crashes [Jonas, D., Carlos; !1173, !1183, !1012]
* Misc. bug fixes and cleanups [Andre, Georges, Christian, Jonas Å., Andre,
Simon, Florian, Carlos, Adam, Marco, Thomas, Elias, Pekka, Jonas D.,
Laurent; !1169, !1168, !1166, !1170, !1167, !1172, !1175, !1176, !1184,
!1126, !1187, !1191, !1195, !1179, !1200, !1193, !1209, !1213, !1208,
#1074, !1223]
Contributors:
Marco Trevisan (Treviño), Elias Aebi, Thomas Hindoe Paaboel Andersen,
Laurent Bigonville, Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Adam Jackson, Andre Moreira Magalhaes, Simon McVittie, Florian Müllner,
Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger,
Phillip Wood, Jonas Ådahl
Translators:
Dušan Kazik [sk], Christian Kirbach [de]
3.36.0
======
* Fix placement of popup windows in multi-monitor setups [Jonas; !1110]

View File

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

View File

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

View File

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

View File

@@ -698,6 +698,7 @@ struct _ClutterActorPrivate
* allocation
*/
ClutterActorBox allocation;
ClutterAllocationFlags allocation_flags;
/* clip, in actor coordinates */
graphene_rect_t clip;
@@ -853,7 +854,6 @@ struct _ClutterActorPrivate
guint needs_paint_volume_update : 1;
guint had_effects_on_last_paint_volume_update : 1;
guint needs_compute_resource_scale : 1;
guint absolute_origin_changed : 1;
};
enum
@@ -1013,6 +1013,7 @@ enum
MOTION_EVENT,
ENTER_EVENT,
LEAVE_EVENT,
ALLOCATION_CHANGED,
TRANSITIONS_COMPLETED,
TOUCH_EVENT,
TRANSITION_STOPPED,
@@ -1197,20 +1198,27 @@ clutter_actor_verify_map_state (ClutterActor *self)
if (CLUTTER_ACTOR_IS_REALIZED (self))
{
if (priv->parent == NULL)
/* all bets are off during reparent when we're potentially realized,
* but should not be according to invariants
*/
if (!CLUTTER_ACTOR_IN_REPARENT (self))
{
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
if (priv->parent == NULL)
{
g_warning ("Realized non-toplevel actor '%s' should "
"have a parent",
_clutter_actor_get_debug_name (self));
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
{
}
else
g_warning ("Realized non-toplevel actor '%s' should "
"have a parent",
_clutter_actor_get_debug_name (self));
}
else if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
{
g_warning ("Realized actor %s has an unrealized parent %s",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
}
else if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
{
g_warning ("Realized actor %s has an unrealized parent %s",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
}
@@ -1220,64 +1228,70 @@ clutter_actor_verify_map_state (ClutterActor *self)
g_warning ("Actor '%s' is mapped but not realized",
_clutter_actor_get_debug_name (self));
if (priv->parent == NULL)
/* remaining bets are off during reparent when we're potentially
* mapped, but should not be according to invariants
*/
if (!CLUTTER_ACTOR_IN_REPARENT (self))
{
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
if (priv->parent == NULL)
{
if (!CLUTTER_ACTOR_IS_VISIBLE (self) &&
!CLUTTER_ACTOR_IN_DESTRUCTION (self))
if (CLUTTER_ACTOR_IS_TOPLEVEL (self))
{
g_warning ("Toplevel actor '%s' is mapped "
"but not visible",
if (!CLUTTER_ACTOR_IS_VISIBLE (self) &&
!CLUTTER_ACTOR_IN_DESTRUCTION (self))
{
g_warning ("Toplevel actor '%s' is mapped "
"but not visible",
_clutter_actor_get_debug_name (self));
}
}
else
{
g_warning ("Mapped actor '%s' should have a parent",
_clutter_actor_get_debug_name (self));
}
}
else
{
g_warning ("Mapped actor '%s' should have a parent",
_clutter_actor_get_debug_name (self));
}
}
else
{
ClutterActor *iter = self;
ClutterActor *iter = self;
/* check for the enable_paint_unmapped flag on the actor
* and parents; if the flag is enabled at any point of this
* branch of the scene graph then all the later checks
* become pointless
*/
while (iter != NULL)
{
if (iter->priv->enable_paint_unmapped)
return;
/* check for the enable_paint_unmapped flag on the actor
* and parents; if the flag is enabled at any point of this
* branch of the scene graph then all the later checks
* become pointless
*/
while (iter != NULL)
{
if (iter->priv->enable_paint_unmapped)
return;
iter = iter->priv->parent;
}
iter = iter->priv->parent;
}
if (!CLUTTER_ACTOR_IS_VISIBLE (priv->parent))
{
g_warning ("Actor '%s' should not be mapped if parent '%s'"
"is not visible",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
if (!CLUTTER_ACTOR_IS_VISIBLE (priv->parent))
{
g_warning ("Actor '%s' should not be mapped if parent '%s'"
"is not visible",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
{
g_warning ("Actor '%s' should not be mapped if parent '%s'"
"is not realized",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent))
{
g_warning ("Actor '%s' should not be mapped if parent '%s'"
"is not realized",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
if (!CLUTTER_ACTOR_IS_TOPLEVEL (priv->parent))
{
if (!CLUTTER_ACTOR_IS_MAPPED (priv->parent))
g_warning ("Actor '%s' is mapped but its non-toplevel "
"parent '%s' is not mapped",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
if (!CLUTTER_ACTOR_IS_TOPLEVEL (priv->parent))
{
if (!CLUTTER_ACTOR_IS_MAPPED (priv->parent))
g_warning ("Actor '%s' is mapped but its non-toplevel "
"parent '%s' is not mapped",
_clutter_actor_get_debug_name (self),
_clutter_actor_get_debug_name (priv->parent));
}
}
}
}
@@ -1572,10 +1586,13 @@ clutter_actor_update_map_state (ClutterActor *self,
_clutter_actor_get_debug_name (priv->parent));
}
/* We want to go in the order "realize, map" and "unmap, unrealize" */
/* If in reparent, we temporarily suspend unmap and unrealize.
*
* We want to go in the order "realize, map" and "unmap, unrealize"
*/
/* Unmap */
if (!should_be_mapped)
if (!should_be_mapped && !CLUTTER_ACTOR_IN_REPARENT (self))
clutter_actor_set_mapped (self, FALSE);
/* Realize */
@@ -1586,7 +1603,7 @@ clutter_actor_update_map_state (ClutterActor *self,
g_assert (!(must_be_realized && !may_be_realized));
/* Unrealize */
if (!may_be_realized)
if (!may_be_realized && !CLUTTER_ACTOR_IN_REPARENT (self))
clutter_actor_unrealize_not_hiding (self);
/* Map */
@@ -2576,13 +2593,15 @@ clutter_actor_notify_if_geometry_changed (ClutterActor *self,
* Return value: %TRUE if the allocation of the #ClutterActor has been
* changed, and %FALSE otherwise
*/
static inline void
static inline gboolean
clutter_actor_set_allocation_internal (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterActorPrivate *priv = self->priv;
GObject *obj;
gboolean x1_changed, y1_changed, x2_changed, y2_changed;
gboolean retval;
ClutterActorBox old_alloc = { 0, };
obj = G_OBJECT (self);
@@ -2597,6 +2616,7 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
y2_changed = priv->allocation.y2 != box->y2;
priv->allocation = *box;
priv->allocation_flags = flags;
/* allocation is authoritative */
priv->needs_width_request = FALSE;
@@ -2621,37 +2641,88 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
priv->content_box_valid = FALSE;
g_object_notify_by_pspec (obj, obj_props[PROP_CONTENT_BOX]);
}
retval = TRUE;
}
else
retval = FALSE;
clutter_actor_notify_if_geometry_changed (self, &old_alloc);
g_object_thaw_notify (obj);
return retval;
}
static void
clutter_actor_real_allocate (ClutterActor *self,
const ClutterActorBox *box)
static void clutter_actor_real_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags);
static inline void
clutter_actor_maybe_layout_children (ClutterActor *self,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
ClutterActorPrivate *priv = self->priv;
g_object_freeze_notify (G_OBJECT (self));
clutter_actor_set_allocation_internal (self, box);
/* we allocate our children before we notify changes in our geometry,
* so that people connecting to properties will be able to get valid
* data out of the sub-tree of the scene graph that has this actor at
* the root.
/* this is going to be a bit hard to follow, so let's put an explanation
* here.
*
* we want ClutterActor to have a default layout manager if the actor was
* created using "g_object_new (CLUTTER_TYPE_ACTOR, NULL)".
*
* we also want any subclass of ClutterActor that does not override the
* ::allocate() virtual function to delegate to a layout manager.
*
* finally, we want to allow people subclassing ClutterActor and overriding
* the ::allocate() vfunc to let Clutter delegate to the layout manager.
*
* on the other hand, we want existing actor subclasses overriding the
* ::allocate() virtual function and chaining up to the parent's
* implementation to continue working without allocating their children
* twice, or without entering an allocation loop.
*
* for the first two points, we check if the class of the actor is
* overridding the ::allocate() virtual function; if it isn't, then we
* follow through with checking whether we have children and a layout
* manager, and eventually calling clutter_layout_manager_allocate().
*
* for the third point, we check the CLUTTER_DELEGATE_LAYOUT flag in the
* allocation flags that we got passed, and if it is present, we continue
* with the check above.
*
* if neither of these two checks yields a positive result, we just
* assume that the ::allocate() virtual function that resulted in this
* function being called will also allocate the children of the actor.
*/
if (CLUTTER_ACTOR_GET_CLASS (self)->allocate == clutter_actor_real_allocate)
goto check_layout;
if ((flags & CLUTTER_DELEGATE_LAYOUT) != 0)
goto check_layout;
return;
check_layout:
if (priv->n_children != 0 &&
priv->layout_manager != NULL)
{
ClutterContainer *container = CLUTTER_CONTAINER (self);
ClutterAllocationFlags children_flags;
ClutterActorBox children_box;
/* normalize the box passed to the layout manager */
children_box.x1 = children_box.y1 = 0.f;
children_box.x2 = box->x2 - box->x1;
children_box.y2 = box->y2 - box->y1;
children_box.x2 = (allocation->x2 - allocation->x1);
children_box.y2 = (allocation->y2 - allocation->y1);
/* remove the DELEGATE_LAYOUT flag; this won't be passed to
* the actor's children, since it refers only to the current
* actor's allocation.
*/
children_flags = flags;
children_flags &= ~CLUTTER_DELEGATE_LAYOUT;
CLUTTER_NOTE (LAYOUT,
"Allocating %d children of %s "
@@ -2659,15 +2730,46 @@ clutter_actor_real_allocate (ClutterActor *self,
"using %s",
priv->n_children,
_clutter_actor_get_debug_name (self),
box->x1,
box->y1,
(box->x2 - box->x1),
(box->y2 - box->y1),
allocation->x1,
allocation->y1,
(allocation->x2 - allocation->x1),
(allocation->y2 - allocation->y1),
G_OBJECT_TYPE_NAME (priv->layout_manager));
clutter_layout_manager_allocate (priv->layout_manager,
CLUTTER_CONTAINER (self),
&children_box);
container,
&children_box,
children_flags);
}
}
static void
clutter_actor_real_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterActorPrivate *priv = self->priv;
gboolean changed;
g_object_freeze_notify (G_OBJECT (self));
changed = clutter_actor_set_allocation_internal (self, box, flags);
/* we allocate our children before we notify changes in our geometry,
* so that people connecting to properties will be able to get valid
* data out of the sub-tree of the scene graph that has this actor at
* the root.
*/
clutter_actor_maybe_layout_children (self, box, flags);
if (changed)
{
ClutterActorBox signal_box = priv->allocation;
ClutterAllocationFlags signal_flags = priv->allocation_flags;
g_signal_emit (self, actor_signals[ALLOCATION_CHANGED], 0,
&signal_box,
signal_flags);
}
g_object_thaw_notify (G_OBJECT (self));
@@ -2706,7 +2808,7 @@ _clutter_actor_propagate_queue_redraw (ClutterActor *self,
if (stop)
break;
self = self->priv->parent;
self = clutter_actor_get_parent (self);
}
}
@@ -2990,6 +3092,96 @@ _clutter_actor_transform_and_project_box (ClutterActor *self,
_clutter_actor_fully_transform_vertices (self, box_vertices, verts, 4);
}
/**
* clutter_actor_get_allocation_vertices:
* @self: A #ClutterActor
* @ancestor: (allow-none): A #ClutterActor to calculate the vertices
* against, or %NULL to use the #ClutterStage
* @verts: (out) (array fixed-size=4): return
* location for an array of 4 #graphene_point3d_t in which to store the result
*
* Calculates the transformed coordinates of the four corners of the
* actor in the plane of @ancestor. The returned vertices relate to
* the #ClutterActorBox coordinates as follows:
*
* - @verts[0] contains (x1, y1)
* - @verts[1] contains (x2, y1)
* - @verts[2] contains (x1, y2)
* - @verts[3] contains (x2, y2)
*
* If @ancestor is %NULL the ancestor will be the #ClutterStage. In
* this case, the coordinates returned will be the coordinates on
* the stage before the projection is applied. This is different from
* the behaviour of clutter_actor_get_abs_allocation_vertices().
*
* Since: 0.6
*/
void
clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
graphene_point3d_t *verts)
{
ClutterActorPrivate *priv;
ClutterActorBox box;
graphene_point3d_t vertices[4];
CoglMatrix modelview;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (ancestor == NULL || CLUTTER_IS_ACTOR (ancestor));
if (ancestor == NULL)
ancestor = _clutter_actor_get_stage_internal (self);
/* Fallback to a NOP transform if the actor isn't parented under a
* stage. */
if (ancestor == NULL)
ancestor = self;
priv = self->priv;
/* if the actor needs to be allocated we force a relayout, so that
* we will have valid values to use in the transformations */
if (priv->needs_allocation)
{
ClutterActor *stage = _clutter_actor_get_stage_internal (self);
if (stage)
_clutter_stage_maybe_relayout (stage);
else
{
box.x1 = box.y1 = 0;
/* The result isn't really meaningful in this case but at
* least try to do something *vaguely* reasonable... */
clutter_actor_get_size (self, &box.x2, &box.y2);
}
}
clutter_actor_get_allocation_box (self, &box);
vertices[0].x = box.x1;
vertices[0].y = box.y1;
vertices[0].z = 0;
vertices[1].x = box.x2;
vertices[1].y = box.y1;
vertices[1].z = 0;
vertices[2].x = box.x1;
vertices[2].y = box.y2;
vertices[2].z = 0;
vertices[3].x = box.x2;
vertices[3].y = box.y2;
vertices[3].z = 0;
_clutter_actor_get_relative_transformation_matrix (self, ancestor,
&modelview);
cogl_matrix_transform_points (&modelview,
3,
sizeof (graphene_point3d_t),
vertices,
sizeof (graphene_point3d_t),
vertices,
4);
}
/**
* clutter_actor_get_abs_allocation_vertices:
* @self: A #ClutterActor
@@ -3224,6 +3416,8 @@ _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
ClutterActor *ancestor,
CoglMatrix *matrix)
{
ClutterActor *parent;
/* Note we terminate before ever calling stage->apply_transform()
* since that would conceptually be relative to the underlying
* window OpenGL coordinates so we'd need a special @ancestor
@@ -3231,9 +3425,10 @@ _clutter_actor_apply_relative_transformation_matrix (ClutterActor *self,
if (self == ancestor)
return;
if (self->priv->parent != NULL)
_clutter_actor_apply_relative_transformation_matrix (self->priv->parent,
ancestor,
parent = clutter_actor_get_parent (self);
if (parent != NULL)
_clutter_actor_apply_relative_transformation_matrix (parent, ancestor,
matrix);
_clutter_actor_apply_modelview_transform (self, matrix);
@@ -4383,7 +4578,8 @@ clutter_actor_remove_child_internal (ClutterActor *self,
clutter_actor_queue_compute_expand (self);
}
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child) &&
!CLUTTER_ACTOR_IN_DESTRUCTION (child))
{
child->priv->needs_compute_resource_scale = TRUE;
g_signal_emit (child, actor_signals[PARENT_SET], 0, self);
@@ -8519,6 +8715,35 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_TYPE_NONE, 1,
CLUTTER_TYPE_PICK_CONTEXT);
/**
* ClutterActor::allocation-changed:
* @actor: the #ClutterActor that emitted the signal
* @box: a #ClutterActorBox with the new allocation
* @flags: #ClutterAllocationFlags for the allocation
*
* The ::allocation-changed signal is emitted when the
* #ClutterActor:allocation property changes. Usually, application
* code should just use the notifications for the :allocation property
* but if you want to track the allocation flags as well, for instance
* to know whether the absolute origin of @actor changed, then you might
* want use this signal instead.
*
* Since: 1.0
*/
actor_signals[ALLOCATION_CHANGED] =
g_signal_new (I_("allocation-changed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
_clutter_marshal_VOID__BOXED_FLAGS,
G_TYPE_NONE, 2,
CLUTTER_TYPE_ACTOR_BOX | G_SIGNAL_TYPE_STATIC_SCOPE,
CLUTTER_TYPE_ALLOCATION_FLAGS);
g_signal_set_va_marshaller (actor_signals[ALLOCATION_CHANGED],
G_TYPE_FROM_CLASS (object_class),
_clutter_marshal_VOID__BOXED_FLAGSv);
/**
* ClutterActor::transitions-completed:
* @actor: a #ClutterActor
@@ -8750,15 +8975,26 @@ static void
_clutter_actor_get_allocation_clip (ClutterActor *self,
ClutterActorBox *clip)
{
ClutterActorPrivate *priv = self->priv;
ClutterActorBox allocation;
/* XXX: we don't care if we get an out of date allocation here
* because clutter_actor_queue_redraw_with_clip knows to ignore
* the clip if the actor's allocation is invalid.
*
* This is noted because clutter_actor_get_allocation_box does some
* unnecessary work to support buggy code with a comment suggesting
* that it could be changed later which would be good for this use
* case!
*/
clutter_actor_get_allocation_box (self, &allocation);
/* NB: clutter_actor_queue_redraw_with_clip expects a box in the
* actor's own coordinate space but the allocation is in parent
* coordinates */
clip->x1 = 0;
clip->y1 = 0;
clip->x2 = priv->allocation.x2 - priv->allocation.x1;
clip->y2 = priv->allocation.y2 - priv->allocation.y1;
clip->x2 = allocation.x2 - allocation.x1;
clip->y2 = allocation.y2 - allocation.y1;
}
void
@@ -8847,21 +9083,25 @@ _clutter_actor_queue_redraw_full (ClutterActor *self,
if (CLUTTER_ACTOR_IN_DESTRUCTION (self))
return;
/* we can ignore unmapped actors, unless they are inside a cloned branch
* of the scene graph, as unmapped actors will simply be left unpainted.
/* we can ignore unmapped actors, unless they have at least one
* mapped clone or they are inside a cloned branch of the scene
* graph, as unmapped actors will simply be left unpainted.
*
* this allows us to ignore redraws queued on leaf nodes when one
* of their parents has been hidden
*/
if (!CLUTTER_ACTOR_IS_MAPPED (self) &&
self->priv->in_cloned_branch == 0 &&
!clutter_actor_has_mapped_clones (self))
{
CLUTTER_NOTE (PAINT,
"Skipping queue_redraw('%s'): mapped=%s, "
"has_mapped_clones=%s",
"mapped_clones=%s, "
"in_cloned_branch=%s",
_clutter_actor_get_debug_name (self),
CLUTTER_ACTOR_IS_MAPPED (self) ? "yes" : "no",
clutter_actor_has_mapped_clones (self) ? "yes" : "no");
clutter_actor_has_mapped_clones (self) ? "yes" : "no",
self->priv->in_cloned_branch != 0 ? "yes" : "no");
return;
}
@@ -10041,7 +10281,8 @@ clutter_actor_adjust_allocation (ClutterActor *self,
static void
clutter_actor_allocate_internal (ClutterActor *self,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
ClutterActorClass *klass;
@@ -10051,7 +10292,7 @@ clutter_actor_allocate_internal (ClutterActor *self,
_clutter_actor_get_debug_name (self));
klass = CLUTTER_ACTOR_GET_CLASS (self);
klass->allocate (self, allocation);
klass->allocate (self, allocation, flags);
CLUTTER_UNSET_PRIVATE_FLAGS (self, CLUTTER_IN_RELAYOUT);
@@ -10064,6 +10305,7 @@ clutter_actor_allocate_internal (ClutterActor *self,
* clutter_actor_allocate:
* @self: A #ClutterActor
* @box: new allocation of the actor, in parent-relative coordinates
* @flags: flags that control the allocation
*
* Assigns the size of a #ClutterActor from the given @box.
*
@@ -10089,11 +10331,12 @@ clutter_actor_allocate_internal (ClutterActor *self,
* Since: 0.8
*/
void
clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box)
clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterActorBox old_allocation, real_allocation;
gboolean origin_changed, size_changed;
gboolean origin_changed, child_moved, size_changed;
gboolean stage_allocation_changed;
ClutterActorPrivate *priv;
@@ -10136,19 +10379,18 @@ clutter_actor_allocate (ClutterActor *self,
real_allocation.x2 = MAX (real_allocation.x2, real_allocation.x1);
real_allocation.y2 = MAX (real_allocation.y2, real_allocation.y1);
origin_changed = (real_allocation.x1 != old_allocation.x1 ||
real_allocation.y1 != old_allocation.y1);
origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED);
child_moved = (real_allocation.x1 != old_allocation.x1 ||
real_allocation.y1 != old_allocation.y1);
size_changed = (real_allocation.x2 != old_allocation.x2 ||
real_allocation.y2 != old_allocation.y2);
priv->absolute_origin_changed = priv->parent
? priv->parent->priv->absolute_origin_changed
: FALSE;
priv->absolute_origin_changed |= origin_changed;
stage_allocation_changed = priv->absolute_origin_changed || size_changed;
if (origin_changed || child_moved || size_changed)
stage_allocation_changed = TRUE;
else
stage_allocation_changed = FALSE;
/* If we get an allocation "out of the blue"
* (we did not queue relayout), then we want to
@@ -10178,10 +10420,24 @@ clutter_actor_allocate (ClutterActor *self,
{
/* If the actor didn't move but needs_allocation is set, we just
* need to allocate the children */
clutter_actor_allocate_internal (self, &real_allocation);
clutter_actor_allocate_internal (self, &real_allocation, flags);
return;
}
/* When ABSOLUTE_ORIGIN_CHANGED is passed in to
* clutter_actor_allocate(), it indicates whether the parent has its
* absolute origin moved; when passed in to ClutterActor::allocate()
* virtual method though, it indicates whether the child has its
* absolute origin moved. So we set it when child_moved is TRUE
*/
if (child_moved)
flags |= CLUTTER_ABSOLUTE_ORIGIN_CHANGED;
/* store the flags here, so that they can be propagated by the
* transition code
*/
self->priv->allocation_flags = flags;
_clutter_actor_create_transition (self, obj_props[PROP_ALLOCATION],
&priv->allocation,
&real_allocation);
@@ -10191,14 +10447,20 @@ clutter_actor_allocate (ClutterActor *self,
* clutter_actor_set_allocation:
* @self: a #ClutterActor
* @box: a #ClutterActorBox
* @flags: allocation flags
*
* Stores the allocation of @self as defined by @box.
*
* This function can only be called from within the implementation of
* the #ClutterActorClass.allocate() virtual function.
*
* The allocation @box should have been adjusted to take into account
* constraints, alignment, and margin properties.
* The allocation should have been adjusted to take into account constraints,
* alignment, and margin properties. If you are implementing a #ClutterActor
* subclass that provides its own layout management policy for its children
* instead of using a #ClutterLayoutManager delegate, you should not call
* this function on the children of @self; instead, you should call
* clutter_actor_allocate(), which will adjust the allocation box for
* you.
*
* This function should only be used by subclasses of #ClutterActor
* that wish to store their allocation but cannot chain up to the
@@ -10206,12 +10468,69 @@ clutter_actor_allocate (ClutterActor *self,
* #ClutterActorClass.allocate() virtual function will call this
* function.
*
* It is important to note that, while chaining up was the recommended
* behaviour for #ClutterActor subclasses prior to the introduction of
* this function, it is recommended to call clutter_actor_set_allocation()
* instead.
*
* If the #ClutterActor is using a #ClutterLayoutManager delegate object
* to handle the allocation of its children, this function will call
* the clutter_layout_manager_allocate() function only if the
* %CLUTTER_DELEGATE_LAYOUT flag is set on @flags, otherwise it is
* expected that the subclass will call clutter_layout_manager_allocate()
* by itself. For instance, the following code:
*
* |[<!-- language="C" -->
* static void
* my_actor_allocate (ClutterActor *actor,
* const ClutterActorBox *allocation,
* ClutterAllocationFlags flags)
* {
* ClutterActorBox new_alloc;
* ClutterAllocationFlags new_flags;
*
* adjust_allocation (allocation, &new_alloc);
*
* new_flags = flags | CLUTTER_DELEGATE_LAYOUT;
*
* // this will use the layout manager set on the actor
* clutter_actor_set_allocation (actor, &new_alloc, new_flags);
* }
* ]|
*
* is equivalent to this:
*
* |[<!-- language="C" -->
* static void
* my_actor_allocate (ClutterActor *actor,
* const ClutterActorBox *allocation,
* ClutterAllocationFlags flags)
* {
* ClutterLayoutManager *layout;
* ClutterActorBox new_alloc;
*
* adjust_allocation (allocation, &new_alloc);
*
* clutter_actor_set_allocation (actor, &new_alloc, flags);
*
* layout = clutter_actor_get_layout_manager (actor);
* clutter_layout_manager_allocate (layout,
* CLUTTER_CONTAINER (actor),
* &new_alloc,
* flags);
* }
* ]|
*
* Since: 1.10
*/
void
clutter_actor_set_allocation (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterActorPrivate *priv;
gboolean changed;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (box != NULL);
@@ -10223,9 +10542,28 @@ clutter_actor_set_allocation (ClutterActor *self,
return;
}
priv = self->priv;
g_object_freeze_notify (G_OBJECT (self));
clutter_actor_set_allocation_internal (self, box);
changed = clutter_actor_set_allocation_internal (self, box, flags);
/* we allocate our children before we notify changes in our geometry,
* so that people connecting to properties will be able to get valid
* data out of the sub-tree of the scene graph that has this actor at
* the root.
*/
clutter_actor_maybe_layout_children (self, box, flags);
if (changed)
{
ClutterActorBox signal_box = priv->allocation;
ClutterAllocationFlags signal_flags = priv->allocation_flags;
g_signal_emit (self, actor_signals[ALLOCATION_CHANGED], 0,
&signal_box,
signal_flags);
}
g_object_thaw_notify (G_OBJECT (self));
}
@@ -12855,7 +13193,7 @@ clutter_actor_add_child_internal (ClutterActor *self,
clutter_actor_queue_compute_expand (self);
}
if (emit_parent_set)
if (emit_parent_set && !CLUTTER_ACTOR_IN_REPARENT (child))
{
child->priv->needs_compute_resource_scale = TRUE;
g_signal_emit (child, actor_signals[PARENT_SET], 0, NULL);
@@ -14698,7 +15036,9 @@ clutter_actor_set_animatable_property (ClutterActor *actor,
break;
case PROP_ALLOCATION:
clutter_actor_allocate_internal (actor, g_value_get_boxed (value));
clutter_actor_allocate_internal (actor,
g_value_get_boxed (value),
actor->priv->allocation_flags);
clutter_actor_queue_redraw (actor);
break;
@@ -15092,6 +15432,7 @@ clutter_actor_get_stage (ClutterActor *actor)
* actor's natural width
* @available_height: the maximum available height, or -1 to use the
* actor's natural height
* @flags: flags controlling the allocation
*
* Allocates @self taking into account the #ClutterActor's
* preferred size, but limiting it to the maximum available width
@@ -15138,7 +15479,7 @@ clutter_actor_get_stage (ClutterActor *actor)
* box.x1 = x; box.y1 = y;
* box.x2 = box.x1 + available_width;
* box.y2 = box.y1 + available_height;
* clutter_actor_allocate (self, &box);
* clutter_actor_allocate (self, &box, flags);
* ]|
*
* This function can be used by fluid layout managers to allocate
@@ -15152,7 +15493,8 @@ clutter_actor_allocate_available_size (ClutterActor *self,
gfloat x,
gfloat y,
gfloat available_width,
gfloat available_height)
gfloat available_height,
ClutterAllocationFlags flags)
{
ClutterActorPrivate *priv;
gfloat width, height;
@@ -15208,12 +15550,13 @@ clutter_actor_allocate_available_size (ClutterActor *self,
box.y1 = y;
box.x2 = box.x1 + width;
box.y2 = box.y1 + height;
clutter_actor_allocate (self, &box);
clutter_actor_allocate (self, &box, flags);
}
/**
* clutter_actor_allocate_preferred_size:
* @self: a #ClutterActor
* @flags: flags controlling the allocation
*
* Allocates the natural size of @self.
*
@@ -15231,7 +15574,8 @@ clutter_actor_allocate_available_size (ClutterActor *self,
* Since: 0.8
*/
void
clutter_actor_allocate_preferred_size (ClutterActor *self)
clutter_actor_allocate_preferred_size (ClutterActor *self,
ClutterAllocationFlags flags)
{
gfloat actor_x, actor_y;
gfloat natural_width, natural_height;
@@ -15265,7 +15609,7 @@ clutter_actor_allocate_preferred_size (ClutterActor *self)
actor_box.x2 = actor_box.x1 + natural_width;
actor_box.y2 = actor_box.y1 + natural_height;
clutter_actor_allocate (self, &actor_box);
clutter_actor_allocate (self, &actor_box, flags);
}
/**
@@ -15276,6 +15620,7 @@ clutter_actor_allocate_preferred_size (ClutterActor *self)
* @y_align: the vertical alignment, between 0 and 1
* @x_fill: whether the actor should fill horizontally
* @y_fill: whether the actor should fill vertically
* @flags: allocation flags to be passed to clutter_actor_allocate()
*
* Allocates @self by taking into consideration the available allocation
* area; an alignment factor on either axis; and whether the actor should
@@ -15302,7 +15647,8 @@ clutter_actor_allocate_align_fill (ClutterActor *self,
gdouble x_align,
gdouble y_align,
gboolean x_fill,
gboolean y_fill)
gboolean y_fill,
ClutterAllocationFlags flags)
{
ClutterActorPrivate *priv;
ClutterActorBox allocation = CLUTTER_ACTOR_BOX_INIT_ZERO;
@@ -15418,7 +15764,7 @@ out:
allocation.x2 = ceilf (allocation.x1 + MAX (child_width, 0));
allocation.y2 = ceilf (allocation.y1 + MAX (child_height, 0));
clutter_actor_allocate (self, &allocation);
clutter_actor_allocate (self, &allocation, flags);
}
/**
@@ -19080,6 +19426,7 @@ should_skip_implicit_transition (ClutterActor *self,
* when those transitions happen
*/
if (!CLUTTER_ACTOR_IS_MAPPED (self) &&
priv->in_cloned_branch == 0 &&
!clutter_actor_has_mapped_clones (self))
return TRUE;
@@ -19613,23 +19960,6 @@ clutter_actor_get_transition (ClutterActor *self,
return clos->transition;
}
/**
* clutter_actor_has_transitions: (skip)
*/
gboolean
clutter_actor_has_transitions (ClutterActor *self)
{
const ClutterAnimationInfo *info;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
info = _clutter_actor_get_animation_info_or_defaults (self);
if (info->transitions == NULL)
return FALSE;
return g_hash_table_size (info->transitions) > 0;
}
/**
* clutter_actor_save_easing_state:
* @self: a #ClutterActor
@@ -20699,41 +21029,31 @@ _clutter_actor_queue_relayout_on_clones (ClutterActor *self)
* clutter_actor_has_mapped_clones:
* @self: a #ClutterActor
*
* Returns whether a #ClutterActor or any parent actors have mapped clones
* that are clone-painting @self.
* Returns whether a #ClutterActor has any mapped clones.
*
* Returns: %TRUE if the actor has mapped clones, %FALSE otherwise
* Return: %TRUE if the actor has mapped clones, and %FALSE otherwise
*
* Since: 1.16
*/
gboolean
clutter_actor_has_mapped_clones (ClutterActor *self)
{
ClutterActor *actor;
ClutterActorPrivate *priv;
GHashTableIter iter;
gpointer key;
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
if (self->priv->in_cloned_branch == 0)
priv = self->priv;
if (priv->clones == NULL)
return FALSE;
for (actor = self; actor; actor = actor->priv->parent)
g_hash_table_iter_init (&iter, priv->clones);
while (g_hash_table_iter_next (&iter, &key, NULL))
{
if (actor->priv->clones)
{
g_hash_table_iter_init (&iter, actor->priv->clones);
while (g_hash_table_iter_next (&iter, &key, NULL))
{
if (CLUTTER_ACTOR_IS_MAPPED (key))
return TRUE;
}
}
/* Clones will force-show their own source actor but not children of
* it, so if we're hidden and an actor up the hierarchy has a clone,
* we won't be visisble.
*/
if (!CLUTTER_ACTOR_IS_VISIBLE (actor))
return FALSE;
if (CLUTTER_ACTOR_IS_MAPPED (key))
return TRUE;
}
return FALSE;

View File

@@ -175,12 +175,9 @@ struct _ClutterActor
* @get_preferred_height: virtual function, used when querying the minimum
* and natural heights of an actor for a given width; it is used by
* clutter_actor_get_preferred_height()
* @allocate: virtual function, used when setting the coordinates of an
* actor; it is used by clutter_actor_allocate(); when overriding this
* function without chaining up, clutter_actor_set_allocation() must be
* called and children must be allocated by the implementation, when
* chaining up though, those things will be done by the parent's
* implementation.
* @allocate: virtual function, used when settings the coordinates of an
* actor; it is used by clutter_actor_allocate(); it must chain up to
* the parent's implementation, or call clutter_actor_set_allocation()
* @apply_transform: virtual function, used when applying the transformations
* to an actor before painting it or when transforming coordinates or
* the allocation; it must chain up to the parent's implementation
@@ -256,7 +253,8 @@ struct _ClutterActorClass
gfloat *min_height_p,
gfloat *natural_height_p);
void (* allocate) (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
/* transformations */
void (* apply_transform) (ClutterActor *actor,
@@ -417,29 +415,38 @@ void clutter_actor_get_preferred_size
gfloat *natural_height_p);
CLUTTER_EXPORT
void clutter_actor_allocate (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_preferred_size (ClutterActor *self);
void clutter_actor_allocate_preferred_size (ClutterActor *self,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_available_size (ClutterActor *self,
gfloat x,
gfloat y,
gfloat available_width,
gfloat available_height);
gfloat available_height,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_allocate_align_fill (ClutterActor *self,
const ClutterActorBox *box,
gdouble x_align,
gdouble y_align,
gboolean x_fill,
gboolean y_fill);
gboolean y_fill,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_set_allocation (ClutterActor *self,
const ClutterActorBox *box);
const ClutterActorBox *box,
ClutterAllocationFlags flags);
CLUTTER_EXPORT
void clutter_actor_get_allocation_box (ClutterActor *self,
ClutterActorBox *box);
CLUTTER_EXPORT
void clutter_actor_get_allocation_vertices (ClutterActor *self,
ClutterActor *ancestor,
graphene_point3d_t *verts);
CLUTTER_EXPORT
gboolean clutter_actor_has_allocation (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_set_size (ClutterActor *self,

View File

@@ -85,7 +85,8 @@ G_DEFINE_TYPE (ClutterAlignConstraint,
static void
source_position_changed (ClutterActor *actor,
GParamSpec *pspec,
const ClutterActorBox *allocation,
ClutterAllocationFlags flags,
ClutterAlignConstraint *align)
{
if (align->actor != NULL)
@@ -409,7 +410,7 @@ clutter_align_constraint_set_source (ClutterAlignConstraint *align,
align->source = source;
if (align->source != NULL)
{
g_signal_connect (align->source, "notify::allocation",
g_signal_connect (align->source, "allocation-changed",
G_CALLBACK (source_position_changed),
align);
g_signal_connect (align->source, "destroy",

View File

@@ -27,23 +27,35 @@
* @short_description: Interface for animatable classes
*
* #ClutterAnimatable is an interface that allows a #GObject class
* to control how an actor will animate a property.
* to control how a #ClutterAnimation will animate a property.
*
* Each #ClutterAnimatable should implement the
* #ClutterAnimatableInterface.interpolate_property() virtual function of the
* interface to compute the animation state between two values of an interval
* depending on a progress factor, expressed as a floating point value.
*
* If a #ClutterAnimatable is animated by a #ClutterAnimation
* instance, the #ClutterAnimation will call
* clutter_animatable_interpolate_property() passing the name of the
* currently animated property; the values interval; and the progress factor.
* The #ClutterAnimatable implementation should return the computed value for
* the animated
* property.
*
* #ClutterAnimatable is available since Clutter 1.0
*/
#include "clutter-build-config.h"
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-animatable.h"
#include "clutter-interval.h"
#include "clutter-debug.h"
#include "clutter-private.h"
#include "deprecated/clutter-animation.h"
G_DEFINE_INTERFACE (ClutterAnimatable, clutter_animatable, G_TYPE_OBJECT);
static void

View File

@@ -42,6 +42,8 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
/**
* 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
* an animatable property
* @get_initial_state: virtual function for retrieving the initial
@@ -51,6 +53,9 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
* @interpolate_value: virtual function for interpolating the progress
* of a property
*
* Base interface for #GObject<!-- -->s that can be animated by a
* a #ClutterAnimation.
*
* Since: 1.0
*/
struct _ClutterAnimatableInterface
@@ -59,6 +64,13 @@ struct _ClutterAnimatableInterface
GTypeInterface parent_iface;
/*< public >*/
gboolean (* animate_property) (ClutterAnimatable *animatable,
ClutterAnimation *animation,
const gchar *property_name,
const GValue *initial_value,
const GValue *final_value,
gdouble progress,
GValue *value);
GParamSpec *(* find_property) (ClutterAnimatable *animatable,
const gchar *property_name);
void (* get_initial_state) (ClutterAnimatable *animatable,

View File

@@ -30,7 +30,9 @@
#ifndef __GI_SCANNER__
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActor, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterActorMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterAlignConstraint, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBackend, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBindConstraint, g_object_unref)
@@ -41,6 +43,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBoxLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterBrightnessContrastEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterCanvas, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterChildMeta, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClickAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterClone, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterColorizeEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterConstraint, g_object_unref)
@@ -50,6 +53,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterDesaturateEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterEffect, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFixedLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFlowLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGestureAction, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterGridLayout, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterImage, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterInputDevice, g_object_unref)

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -159,8 +159,7 @@ static inline void
click_action_set_pressed (ClutterClickAction *action,
gboolean is_pressed)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
is_pressed = !!is_pressed;
@@ -175,8 +174,7 @@ static inline void
click_action_set_held (ClutterClickAction *action,
gboolean is_held)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
is_held = !!is_held;
@@ -191,8 +189,7 @@ static gboolean
click_action_emit_long_press (gpointer data)
{
ClutterClickAction *action = data;
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
gboolean result;
@@ -216,8 +213,7 @@ click_action_emit_long_press (gpointer data)
static inline void
click_action_query_long_press (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
gboolean result = FALSE;
gint timeout;
@@ -253,8 +249,7 @@ click_action_query_long_press (ClutterClickAction *action)
static inline void
click_action_cancel_long_press (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
if (priv->long_press_id != 0)
{
@@ -277,8 +272,7 @@ on_event (ClutterActor *actor,
ClutterEvent *event,
ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
gboolean has_button = TRUE;
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
@@ -348,8 +342,7 @@ on_captured_event (ClutterActor *stage,
ClutterEvent *event,
ClutterClickAction *action)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
ClutterActor *actor;
ClutterModifierType modifier_state;
gboolean has_button = TRUE;
@@ -441,8 +434,7 @@ clutter_click_action_set_actor (ClutterActorMeta *meta,
ClutterActor *actor)
{
ClutterClickAction *action = CLUTTER_CLICK_ACTION (meta);
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (action);
ClutterClickActionPrivate *priv = action->priv;
if (priv->event_id != 0)
{
@@ -496,8 +488,7 @@ clutter_click_action_set_property (GObject *gobject,
const GValue *value,
GParamSpec *pspec)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
switch (prop_id)
{
@@ -521,8 +512,7 @@ clutter_click_action_get_property (GObject *gobject,
GValue *value,
GParamSpec *pspec)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
switch (prop_id)
{
@@ -551,8 +541,7 @@ clutter_click_action_get_property (GObject *gobject,
static void
clutter_click_action_dispose (GObject *gobject)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (CLUTTER_CLICK_ACTION (gobject));
ClutterClickActionPrivate *priv = CLUTTER_CLICK_ACTION (gobject)->priv;
g_clear_signal_handler (&priv->event_id,
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)));
@@ -710,11 +699,9 @@ clutter_click_action_class_init (ClutterClickActionClass *klass)
static void
clutter_click_action_init (ClutterClickAction *self)
{
ClutterClickActionPrivate *priv =
clutter_click_action_get_instance_private (self);
priv->long_press_threshold = -1;
priv->long_press_duration = -1;
self->priv = clutter_click_action_get_instance_private (self);
self->priv->long_press_threshold = -1;
self->priv->long_press_duration = -1;
}
/**
@@ -754,7 +741,7 @@ clutter_click_action_release (ClutterClickAction *action)
g_return_if_fail (CLUTTER_IS_CLICK_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
priv = action->priv;
if (!priv->is_held)
return;
@@ -780,13 +767,9 @@ clutter_click_action_release (ClutterClickAction *action)
guint
clutter_click_action_get_button (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action);
return priv->press_button;
return action->priv->press_button;
}
/**
@@ -802,13 +785,9 @@ clutter_click_action_get_button (ClutterClickAction *action)
ClutterModifierType
clutter_click_action_get_state (ClutterClickAction *action)
{
ClutterClickActionPrivate *priv;
g_return_val_if_fail (CLUTTER_IS_CLICK_ACTION (action), 0);
priv = clutter_click_action_get_instance_private (action);
return priv->modifier_state;
return action->priv->modifier_state;
}
/**
@@ -826,15 +805,11 @@ clutter_click_action_get_coords (ClutterClickAction *action,
gfloat *press_x,
gfloat *press_y)
{
ClutterClickActionPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTION (action));
priv = clutter_click_action_get_instance_private (action);
if (press_x != NULL)
*press_x = priv->press_x;
*press_x = action->priv->press_x;
if (press_y != NULL)
*press_y = priv->press_y;
*press_y = action->priv->press_y;
}

View File

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

View File

@@ -240,14 +240,15 @@ clutter_clone_has_overlaps (ClutterActor *actor)
static void
clutter_clone_allocate (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorClass *parent_class;
/* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
parent_class->allocate (self, box);
parent_class->allocate (self, box, flags);
if (priv->clone_source == NULL)
return;
@@ -257,7 +258,7 @@ clutter_clone_allocate (ClutterActor *self,
*/
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
!clutter_actor_has_allocation (priv->clone_source))
clutter_actor_allocate_preferred_size (priv->clone_source);
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
#if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented
@@ -272,7 +273,7 @@ clutter_clone_allocate (ClutterActor *self,
* paint cycle, we can safely give it as much size as it requires
*/
if (clutter_actor_get_parent (priv->clone_source) == NULL)
clutter_actor_allocate_preferred_size (priv->clone_source);
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
#endif
}

View File

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

View File

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

View File

@@ -1,42 +0,0 @@
/*
* Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
* Copyright (C) 2020 Red Hat Inc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_DAMAGE_HISTORY_H
#define CLUTTER_DAMAGE_HISTORY_H
#include <cairo.h>
#include <glib.h>
typedef struct _ClutterDamageHistory ClutterDamageHistory;
ClutterDamageHistory * clutter_damage_history_new (void);
void clutter_damage_history_free (ClutterDamageHistory *history);
gboolean clutter_damage_history_is_age_valid (ClutterDamageHistory *history,
int age);
void clutter_damage_history_record (ClutterDamageHistory *history,
const cairo_region_t *damage);
void clutter_damage_history_step (ClutterDamageHistory *history);
const cairo_region_t * clutter_damage_history_lookup (ClutterDamageHistory *history,
int age);
#endif /* CLUTTER_DAMAGE_HISTORY_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -136,6 +136,7 @@
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "deprecated/clutter-container.h"
#include "deprecated/clutter-alpha.h"
#include "clutter-debug.h"
#include "clutter-layout-manager.h"
@@ -163,6 +164,7 @@ G_DEFINE_ABSTRACT_TYPE (ClutterLayoutManager,
G_TYPE_INITIALLY_UNOWNED)
static GQuark quark_layout_meta = 0;
static GQuark quark_layout_alpha = 0;
static guint manager_signals[LAST_SIGNAL] = { 0, };
@@ -253,7 +255,8 @@ layout_manager_real_get_preferred_height (ClutterLayoutManager *manager,
static void
layout_manager_real_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "allocate");
}
@@ -298,12 +301,96 @@ layout_manager_real_get_child_meta_type (ClutterLayoutManager *manager)
return G_TYPE_INVALID;
}
/* XXX:2.0 - Remove */
static ClutterAlpha *
layout_manager_real_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode)
{
ClutterTimeline *timeline;
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha != NULL)
{
clutter_alpha_set_mode (alpha, mode);
timeline = clutter_alpha_get_timeline (alpha);
clutter_timeline_set_duration (timeline, duration);
clutter_timeline_rewind (timeline);
return alpha;
};
timeline = clutter_timeline_new (duration);
alpha = clutter_alpha_new_full (timeline, mode);
/* let the alpha take ownership of the timeline */
g_object_unref (timeline);
g_signal_connect_swapped (timeline, "new-frame",
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
g_object_set_qdata_full (G_OBJECT (manager),
quark_layout_alpha, alpha,
(GDestroyNotify) g_object_unref);
clutter_timeline_start (timeline);
return alpha;
}
/* XXX:2.0 - Remove */
static gdouble
layout_manager_real_get_animation_progress (ClutterLayoutManager *manager)
{
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha == NULL)
return 1.0;
return clutter_alpha_get_alpha (alpha);
}
/* XXX:2.0 - Remove */
static void
layout_manager_real_end_animation (ClutterLayoutManager *manager)
{
ClutterTimeline *timeline;
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha == NULL)
return;
timeline = clutter_alpha_get_timeline (alpha);
g_assert (timeline != NULL);
if (clutter_timeline_is_playing (timeline))
clutter_timeline_stop (timeline);
g_signal_handlers_disconnect_by_func (timeline,
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
g_object_set_qdata (G_OBJECT (manager), quark_layout_alpha, NULL);
clutter_layout_manager_layout_changed (manager);
}
static void
clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass)
{
quark_layout_meta =
g_quark_from_static_string ("clutter-layout-manager-child-meta");
/* XXX:2.0 - Remove */
quark_layout_alpha =
g_quark_from_static_string ("clutter-layout-manager-alpha");
klass->get_preferred_width = layout_manager_real_get_preferred_width;
klass->get_preferred_height = layout_manager_real_get_preferred_height;
klass->allocate = layout_manager_real_allocate;
@@ -311,6 +398,9 @@ clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass)
klass->get_child_meta_type = layout_manager_real_get_child_meta_type;
/* XXX:2.0 - Remove */
klass->begin_animation = layout_manager_real_begin_animation;
klass->get_animation_progress = layout_manager_real_get_animation_progress;
klass->end_animation = layout_manager_real_end_animation;
klass->set_container = layout_manager_real_set_container;
/**
@@ -433,6 +523,7 @@ clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager,
* @container: the #ClutterContainer using @manager
* @allocation: the #ClutterActorBox containing the allocated area
* of @container
* @flags: the allocation flags
*
* Allocates the children of @container given an area
*
@@ -443,7 +534,8 @@ clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager,
void
clutter_layout_manager_allocate (ClutterLayoutManager *manager,
ClutterContainer *container,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
ClutterLayoutManagerClass *klass;
@@ -452,7 +544,7 @@ clutter_layout_manager_allocate (ClutterLayoutManager *manager,
g_return_if_fail (allocation != NULL);
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
klass->allocate (manager, container, allocation);
klass->allocate (manager, container, allocation, flags);
}
/**

View File

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

View File

@@ -199,7 +199,7 @@ master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock)
stages = clutter_stage_manager_peek_stages (stage_manager);
for (l = stages; l != NULL; l = l->next)
clutter_stage_schedule_update (l->data);
_clutter_stage_schedule_update (l->data);
}
static GSList *
@@ -252,7 +252,7 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
if (master_clock->timelines ||
_clutter_stage_has_queued_events (l->data) ||
_clutter_stage_needs_update (l->data))
clutter_stage_schedule_update (l->data);
_clutter_stage_schedule_update (l->data);
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -65,6 +65,7 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#define CLUTTER_ACTOR_IS_TOPLEVEL(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IS_TOPLEVEL) != FALSE)
#define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) != FALSE)
#define CLUTTER_ACTOR_IN_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_PICK(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PICK) != FALSE)
#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE)
@@ -98,6 +99,7 @@ typedef enum
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,

View File

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

View File

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

View File

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

View File

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

View File

@@ -74,6 +74,7 @@ void _clutter_stage_queue_event (ClutterStage *stage,
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
void _clutter_stage_process_queued_events (ClutterStage *stage);
void _clutter_stage_update_input_devices (ClutterStage *stage);
void _clutter_stage_schedule_update (ClutterStage *stage);
gint64 _clutter_stage_get_update_time (ClutterStage *stage);
void _clutter_stage_clear_update_time (ClutterStage *stage);
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
@@ -138,6 +139,8 @@ void _clutter_stage_presented (ClutterStage *stag
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info);
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
ClutterActor *actor);

View File

@@ -20,28 +20,17 @@
#include "clutter/clutter-stage-view.h"
void clutter_stage_view_after_paint (ClutterStageView *view,
cairo_region_t *redraw_clip);
void clutter_stage_view_before_swap_buffer (ClutterStageView *view,
const cairo_region_t *swap_region);
void clutter_stage_view_after_paint (ClutterStageView *view);
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
void clutter_stage_view_invalidate_viewport (ClutterStageView *view);
void clutter_stage_view_set_viewport (ClutterStageView *view,
float x,
float y,
float width,
float height);
void clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
gboolean dirty);
gboolean clutter_stage_view_is_dirty_projection (ClutterStageView *view);
void clutter_stage_view_invalidate_projection (ClutterStageView *view);
void clutter_stage_view_set_projection (ClutterStageView *view,
const CoglMatrix *matrix);
void clutter_stage_view_set_dirty_projection (ClutterStageView *view,
gboolean dirty);
void clutter_stage_view_add_redraw_clip (ClutterStageView *view,
const cairo_rectangle_int_t *clip);
@@ -54,12 +43,4 @@ const cairo_region_t * clutter_stage_view_peek_redraw_clip (ClutterStageView *vi
cairo_region_t * clutter_stage_view_take_redraw_clip (ClutterStageView *view);
CoglScanout * clutter_stage_view_take_scanout (ClutterStageView *view);
void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view,
const cairo_rectangle_int_t *src_rect,
int dst_width,
int dst_height,
cairo_rectangle_int_t *dst_rect);
#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */

View File

@@ -23,20 +23,16 @@
#include <cairo-gobject.h>
#include <math.h>
#include "clutter/clutter-damage-history.h"
#include "clutter/clutter-private.h"
#include "clutter/clutter-mutter.h"
#include "cogl/cogl.h"
enum
{
PROP_0,
PROP_NAME,
PROP_LAYOUT,
PROP_FRAMEBUFFER,
PROP_OFFSCREEN,
PROP_USE_SHADOWFB,
PROP_SHADOWFB,
PROP_SCALE,
PROP_LAST
@@ -46,8 +42,6 @@ static GParamSpec *obj_props[PROP_LAST];
typedef struct _ClutterStageViewPrivate
{
char *name;
cairo_rectangle_int_t layout;
float scale;
CoglFramebuffer *framebuffer;
@@ -55,18 +49,8 @@ typedef struct _ClutterStageViewPrivate
CoglOffscreen *offscreen;
CoglPipeline *offscreen_pipeline;
gboolean use_shadowfb;
struct {
struct {
CoglDmaBufHandle *handles[2];
int current_idx;
ClutterDamageHistory *damage_history;
} dma_buf;
CoglOffscreen *framebuffer;
} shadow;
CoglScanout *next_scanout;
CoglOffscreen *shadowfb;
CoglPipeline *shadowfb_pipeline;
gboolean has_redraw_clip;
cairo_region_t *redraw_clip;
@@ -103,8 +87,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
if (priv->offscreen)
return priv->offscreen;
else if (priv->shadow.framebuffer)
return priv->shadow.framebuffer;
else if (priv->shadowfb)
return priv->shadowfb;
else
return priv->framebuffer;
}
@@ -164,6 +148,19 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
}
static void
clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->shadowfb_pipeline)
return;
priv->shadowfb_pipeline =
clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
}
void
clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
{
@@ -173,563 +170,85 @@ clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
}
void
clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view,
const cairo_rectangle_int_t *src_rect,
int dst_width,
int dst_height,
cairo_rectangle_int_t *dst_rect)
{
ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view);
return view_class->transform_rect_to_onscreen (view,
src_rect,
dst_width,
dst_height,
dst_rect);
}
static void
paint_transformed_framebuffer (ClutterStageView *view,
CoglPipeline *pipeline,
CoglFramebuffer *src_framebuffer,
CoglFramebuffer *dst_framebuffer,
const cairo_region_t *redraw_clip)
clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
CoglPipeline *pipeline,
CoglFramebuffer *src_framebuffer,
CoglFramebuffer *dst_framebuffer,
gboolean can_blit)
{
CoglMatrix matrix;
unsigned int n_rectangles, i;
int dst_width, dst_height;
cairo_rectangle_int_t view_layout;
cairo_rectangle_int_t onscreen_layout;
float view_scale;
float *coordinates;
dst_width = cogl_framebuffer_get_width (dst_framebuffer);
dst_height = cogl_framebuffer_get_height (dst_framebuffer);
clutter_stage_view_get_layout (view, &view_layout);
clutter_stage_view_transform_rect_to_onscreen (view,
&(cairo_rectangle_int_t) {
.width = view_layout.width,
.height = view_layout.height,
},
view_layout.width,
view_layout.height,
&onscreen_layout);
view_scale = clutter_stage_view_get_scale (view);
/* First, try with blit */
if (can_blit)
{
if (cogl_blit_framebuffer (src_framebuffer,
dst_framebuffer,
0, 0,
0, 0,
cogl_framebuffer_get_width (dst_framebuffer),
cogl_framebuffer_get_height (dst_framebuffer),
NULL))
return;
}
/* If blit fails, fallback to the slower painting method */
cogl_framebuffer_push_matrix (dst_framebuffer);
cogl_matrix_init_identity (&matrix);
cogl_matrix_scale (&matrix,
1.0 / (dst_width / 2.0),
-1.0 / (dst_height / 2.0), 0);
cogl_matrix_translate (&matrix,
-(dst_width / 2.0),
-(dst_height / 2.0), 0);
cogl_matrix_translate (&matrix, -1, 1, 0);
cogl_matrix_scale (&matrix, 2, -2, 0);
cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
cogl_framebuffer_set_viewport (dst_framebuffer,
0, 0, dst_width, dst_height);
n_rectangles = cairo_region_num_rectangles (redraw_clip);
coordinates = g_newa (float, 2 * 4 * n_rectangles);
for (i = 0; i < n_rectangles; i++)
{
cairo_rectangle_int_t src_rect;
cairo_rectangle_int_t dst_rect;
cairo_region_get_rectangle (redraw_clip, i, &src_rect);
_clutter_util_rectangle_offset (&src_rect,
-view_layout.x,
-view_layout.y,
&src_rect);
clutter_stage_view_transform_rect_to_onscreen (view,
&src_rect,
onscreen_layout.width,
onscreen_layout.height,
&dst_rect);
coordinates[i * 8 + 0] = (float) dst_rect.x * view_scale;
coordinates[i * 8 + 1] = (float) dst_rect.y * view_scale;
coordinates[i * 8 + 2] = ((float) (dst_rect.x + dst_rect.width) *
view_scale);
coordinates[i * 8 + 3] = ((float) (dst_rect.y + dst_rect.height) *
view_scale);
coordinates[i * 8 + 4] = (((float) dst_rect.x / (float) dst_width) *
view_scale);
coordinates[i * 8 + 5] = (((float) dst_rect.y / (float) dst_height) *
view_scale);
coordinates[i * 8 + 6] = ((float) (dst_rect.x + dst_rect.width) /
(float) dst_width) * view_scale;
coordinates[i * 8 + 7] = ((float) (dst_rect.y + dst_rect.height) /
(float) dst_height) * view_scale;
}
cogl_framebuffer_draw_textured_rectangles (dst_framebuffer,
pipeline,
coordinates,
n_rectangles);
cogl_framebuffer_draw_rectangle (dst_framebuffer,
pipeline,
0, 0, 1, 1);
cogl_framebuffer_pop_matrix (dst_framebuffer);
}
static gboolean
is_shadowfb_double_buffered (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
return priv->shadow.dma_buf.handles[0] && priv->shadow.dma_buf.handles[1];
}
static gboolean
init_dma_buf_shadowfbs (ClutterStageView *view,
CoglContext *cogl_context,
int width,
int height,
GError **error)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
CoglFramebuffer *initial_shadowfb;
if (!cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Buffer age not supported");
return FALSE;
}
if (!cogl_is_onscreen (priv->framebuffer))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"Tried to use shadow buffer without onscreen");
return FALSE;
}
priv->shadow.dma_buf.handles[0] = cogl_renderer_create_dma_buf (cogl_renderer,
width, height,
error);
if (!priv->shadow.dma_buf.handles[0])
return FALSE;
priv->shadow.dma_buf.handles[1] = cogl_renderer_create_dma_buf (cogl_renderer,
width, height,
error);
if (!priv->shadow.dma_buf.handles[1])
{
g_clear_pointer (&priv->shadow.dma_buf.handles[0],
cogl_dma_buf_handle_free);
return FALSE;
}
priv->shadow.dma_buf.damage_history = clutter_damage_history_new ();
initial_shadowfb =
cogl_dma_buf_handle_get_framebuffer (priv->shadow.dma_buf.handles[0]);
priv->shadow.framebuffer = cogl_object_ref (initial_shadowfb);
return TRUE;
}
static CoglOffscreen *
create_offscreen_framebuffer (CoglContext *context,
int width,
int height,
GError **error)
{
CoglOffscreen *framebuffer;
CoglTexture2D *texture;
texture = cogl_texture_2d_new_with_size (context, width, height);
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
FALSE);
if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
{
cogl_object_unref (texture);
return FALSE;
}
framebuffer = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (framebuffer), error))
{
cogl_object_unref (framebuffer);
return FALSE;
}
return framebuffer;
}
static gboolean
init_fallback_shadowfb (ClutterStageView *view,
CoglContext *cogl_context,
int width,
int height,
GError **error)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
CoglOffscreen *offscreen;
offscreen = create_offscreen_framebuffer (cogl_context, width, height, error);
if (!offscreen)
return FALSE;
priv->shadow.framebuffer = offscreen;
return TRUE;
}
static void
init_shadowfb (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
g_autoptr (GError) error = NULL;
int width;
int height;
CoglContext *cogl_context;
width = cogl_framebuffer_get_width (priv->framebuffer);
height = cogl_framebuffer_get_height (priv->framebuffer);
cogl_context = cogl_framebuffer_get_context (priv->framebuffer);
if (init_dma_buf_shadowfbs (view, cogl_context, width, height, &error))
{
g_message ("Initialized double buffered shadow fb for %s", priv->name);
return;
}
g_warning ("Failed to initialize double buffered shadow fb for %s: %s",
priv->name, error->message);
g_clear_error (&error);
if (!init_fallback_shadowfb (view, cogl_context, width, height, &error))
{
g_warning ("Failed to initialize single buffered shadow fb for %s: %s",
priv->name, error->message);
}
else
{
g_message ("Initialized single buffered shadow fb for %s", priv->name);
}
}
void
clutter_stage_view_after_paint (ClutterStageView *view,
cairo_region_t *redraw_clip)
clutter_stage_view_after_paint (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->offscreen)
{
gboolean can_blit;
CoglMatrix matrix;
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
can_blit = cogl_matrix_is_identity (&matrix);
if (priv->shadow.framebuffer)
if (priv->shadowfb)
{
paint_transformed_framebuffer (view,
priv->offscreen_pipeline,
priv->offscreen,
priv->shadow.framebuffer,
redraw_clip);
clutter_stage_view_copy_to_framebuffer (view,
priv->offscreen_pipeline,
priv->offscreen,
priv->shadowfb,
can_blit);
}
else
{
paint_transformed_framebuffer (view,
priv->offscreen_pipeline,
priv->offscreen,
priv->framebuffer,
redraw_clip);
}
}
}
static gboolean
is_tile_dirty (cairo_rectangle_int_t *tile,
uint8_t *current_data,
uint8_t *prev_data,
int bpp,
int stride)
{
int y;
for (y = tile->y; y < tile->y + tile->height; y++)
{
if (memcmp (prev_data + y * stride + tile->x * bpp,
current_data + y * stride + tile->x * bpp,
tile->width * bpp) != 0)
return TRUE;
}
return FALSE;
}
static int
flip_dma_buf_idx (int idx)
{
return (idx + 1) % 2;
}
static cairo_region_t *
find_damaged_tiles (ClutterStageView *view,
const cairo_region_t *damage_region,
GError **error)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
cairo_region_t *tile_damage_region;
cairo_rectangle_int_t damage_extents;
cairo_rectangle_int_t fb_rect;
int prev_dma_buf_idx;
CoglDmaBufHandle *prev_dma_buf_handle;
uint8_t *prev_data;
int current_dma_buf_idx;
CoglDmaBufHandle *current_dma_buf_handle;
uint8_t *current_data;
int width, height, stride, bpp;
int tile_x_min, tile_x_max;
int tile_y_min, tile_y_max;
int tile_x, tile_y;
const int tile_size = 16;
prev_dma_buf_idx = flip_dma_buf_idx (priv->shadow.dma_buf.current_idx);
prev_dma_buf_handle = priv->shadow.dma_buf.handles[prev_dma_buf_idx];
current_dma_buf_idx = priv->shadow.dma_buf.current_idx;
current_dma_buf_handle = priv->shadow.dma_buf.handles[current_dma_buf_idx];
width = cogl_dma_buf_handle_get_width (current_dma_buf_handle);
height = cogl_dma_buf_handle_get_height (current_dma_buf_handle);
stride = cogl_dma_buf_handle_get_stride (current_dma_buf_handle);
bpp = cogl_dma_buf_handle_get_bpp (current_dma_buf_handle);
cogl_framebuffer_finish (priv->shadow.framebuffer);
if (!cogl_dma_buf_handle_sync_read_start (prev_dma_buf_handle, error))
return NULL;
if (!cogl_dma_buf_handle_sync_read_start (current_dma_buf_handle, error))
goto err_sync_read_current;
prev_data = cogl_dma_buf_handle_mmap (prev_dma_buf_handle, error);
if (!prev_data)
goto err_mmap_prev;
current_data = cogl_dma_buf_handle_mmap (current_dma_buf_handle, error);
if (!current_data)
goto err_mmap_current;
fb_rect = (cairo_rectangle_int_t) {
.width = width,
.height = height,
};
cairo_region_get_extents (damage_region, &damage_extents);
tile_x_min = damage_extents.x / tile_size;
tile_x_max = ((damage_extents.x + damage_extents.width + tile_size - 1) /
tile_size);
tile_y_min = damage_extents.y / tile_size;
tile_y_max = ((damage_extents.y + damage_extents.height + tile_size - 1) /
tile_size);
tile_damage_region = cairo_region_create ();
for (tile_y = tile_y_min; tile_y <= tile_y_max; tile_y++)
{
for (tile_x = tile_x_min; tile_x <= tile_x_max; tile_x++)
{
cairo_rectangle_int_t tile = {
.x = tile_x * tile_size,
.y = tile_y * tile_size,
.width = tile_size,
.height = tile_size,
};
if (cairo_region_contains_rectangle (damage_region, &tile) ==
CAIRO_REGION_OVERLAP_OUT)
continue;
_clutter_util_rectangle_intersection (&tile, &fb_rect, &tile);
if (is_tile_dirty (&tile, current_data, prev_data, bpp, stride))
cairo_region_union_rectangle (tile_damage_region, &tile);
clutter_stage_view_copy_to_framebuffer (view,
priv->offscreen_pipeline,
priv->offscreen,
priv->framebuffer,
can_blit);
}
}
if (!cogl_dma_buf_handle_sync_read_end (prev_dma_buf_handle, error))
if (priv->shadowfb)
{
g_warning ("Failed to end DMA buffer read synchronization: %s",
(*error)->message);
g_clear_error (error);
clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
clutter_stage_view_copy_to_framebuffer (view,
priv->shadowfb_pipeline,
priv->shadowfb,
priv->framebuffer,
TRUE);
}
if (!cogl_dma_buf_handle_sync_read_end (current_dma_buf_handle, error))
{
g_warning ("Failed to end DMA buffer read synchronization: %s",
(*error)->message);
g_clear_error (error);
}
cogl_dma_buf_handle_munmap (prev_dma_buf_handle, prev_data, NULL);
cogl_dma_buf_handle_munmap (current_dma_buf_handle, current_data, NULL);
cairo_region_intersect (tile_damage_region, damage_region);
return tile_damage_region;
err_mmap_current:
cogl_dma_buf_handle_munmap (prev_dma_buf_handle, prev_data, NULL);
err_mmap_prev:
cogl_dma_buf_handle_sync_read_end (current_dma_buf_handle, NULL);
err_sync_read_current:
cogl_dma_buf_handle_sync_read_end (prev_dma_buf_handle, NULL);
return NULL;
}
static void
swap_dma_buf_framebuffer (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
int next_idx;
CoglDmaBufHandle *next_dma_buf_handle;
CoglOffscreen *next_framebuffer;
next_idx = ((priv->shadow.dma_buf.current_idx + 1) %
G_N_ELEMENTS (priv->shadow.dma_buf.handles));
priv->shadow.dma_buf.current_idx = next_idx;
next_dma_buf_handle = priv->shadow.dma_buf.handles[next_idx];
next_framebuffer =
cogl_dma_buf_handle_get_framebuffer (next_dma_buf_handle);
cogl_clear_object (&priv->shadow.framebuffer);
priv->shadow.framebuffer = cogl_object_ref (next_framebuffer);
}
static void
copy_shadowfb_to_onscreen (ClutterStageView *view,
const cairo_region_t *swap_region)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
ClutterDamageHistory *damage_history = priv->shadow.dma_buf.damage_history;
cairo_region_t *damage_region;
int age;
int i;
if (cairo_region_is_empty (swap_region))
{
cairo_rectangle_int_t full_damage = {
.width = cogl_framebuffer_get_width (priv->framebuffer),
.height = cogl_framebuffer_get_height (priv->framebuffer),
};
damage_region = cairo_region_create_rectangle (&full_damage);
}
else
{
damage_region = cairo_region_copy (swap_region);
}
if (is_shadowfb_double_buffered (view))
{
CoglOnscreen *onscreen = COGL_ONSCREEN (priv->framebuffer);
cairo_region_t *changed_region;
if (cogl_onscreen_get_frame_counter (onscreen) >= 1)
{
g_autoptr (GError) error = NULL;
changed_region = find_damaged_tiles (view, damage_region, &error);
if (!changed_region)
{
int other_dma_buf_idx;
g_warning ("Disabling actual damage detection: %s",
error->message);
other_dma_buf_idx =
flip_dma_buf_idx (priv->shadow.dma_buf.current_idx);
g_clear_pointer (&priv->shadow.dma_buf.handles[other_dma_buf_idx],
cogl_dma_buf_handle_free);
}
}
else
{
changed_region = cairo_region_copy (damage_region);
}
if (changed_region)
{
int buffer_age;
clutter_damage_history_record (damage_history, changed_region);
buffer_age = cogl_onscreen_get_buffer_age (onscreen);
if (clutter_damage_history_is_age_valid (damage_history, buffer_age))
{
for (age = 1; age <= buffer_age; age++)
{
const cairo_region_t *old_damage;
old_damage = clutter_damage_history_lookup (damage_history, age);
cairo_region_union (changed_region, old_damage);
}
cairo_region_destroy (damage_region);
damage_region = g_steal_pointer (&changed_region);
}
else
{
cairo_region_destroy (changed_region);
}
clutter_damage_history_step (damage_history);
}
}
for (i = 0; i < cairo_region_num_rectangles (damage_region); i++)
{
g_autoptr (GError) error = NULL;
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (damage_region, i, &rect);
if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
priv->framebuffer,
rect.x, rect.y,
rect.x, rect.y,
rect.width, rect.height,
&error))
{
g_warning ("Failed to blit shadow buffer: %s", error->message);
cairo_region_destroy (damage_region);
return;
}
}
cairo_region_destroy (damage_region);
if (is_shadowfb_double_buffered (view))
swap_dma_buf_framebuffer (view);
}
void
clutter_stage_view_before_swap_buffer (ClutterStageView *view,
const cairo_region_t *swap_region)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->shadow.framebuffer)
copy_shadowfb_to_onscreen (view, swap_region);
}
float
@@ -741,47 +260,6 @@ clutter_stage_view_get_scale (ClutterStageView *view)
return priv->scale;
}
typedef void (*FrontBufferCallback) (CoglFramebuffer *framebuffer,
gconstpointer user_data);
static void
clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
FrontBufferCallback callback,
gconstpointer user_data)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->offscreen)
{
callback (priv->offscreen, user_data);
}
else if (priv->shadow.framebuffer)
{
if (is_shadowfb_double_buffered (view))
{
int i;
for (i = 0; i < G_N_ELEMENTS (priv->shadow.dma_buf.handles); i++)
{
CoglDmaBufHandle *handle = priv->shadow.dma_buf.handles[i];
CoglFramebuffer *framebuffer =
cogl_dma_buf_handle_get_framebuffer (handle);
callback (framebuffer, user_data);
}
}
else
{
callback (priv->shadow.framebuffer, user_data);
}
}
else
{
callback (priv->framebuffer, user_data);
}
}
gboolean
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
{
@@ -792,47 +270,13 @@ clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
}
void
clutter_stage_view_invalidate_viewport (ClutterStageView *view)
clutter_stage_view_set_dirty_viewport (ClutterStageView *view,
gboolean dirty)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
priv->dirty_viewport = TRUE;
}
static void
set_framebuffer_viewport (CoglFramebuffer *framebuffer,
gconstpointer user_data)
{
const graphene_rect_t *rect = user_data;
cogl_framebuffer_set_viewport (framebuffer,
rect->origin.x,
rect->origin.y,
rect->size.width,
rect->size.height);
}
void
clutter_stage_view_set_viewport (ClutterStageView *view,
float x,
float y,
float width,
float height)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
graphene_rect_t rect;
priv->dirty_viewport = FALSE;
rect = (graphene_rect_t) {
.origin = { .x = x, .y = y },
.size = { .width = width, .height = height },
};
clutter_stage_view_foreach_front_buffer (view,
set_framebuffer_viewport,
&rect);
priv->dirty_viewport = dirty;
}
gboolean
@@ -844,33 +288,14 @@ clutter_stage_view_is_dirty_projection (ClutterStageView *view)
return priv->dirty_projection;
}
static void
set_framebuffer_projection_matrix (CoglFramebuffer *framebuffer,
gconstpointer user_data)
{
cogl_framebuffer_set_projection_matrix (framebuffer, user_data);
}
void
clutter_stage_view_invalidate_projection (ClutterStageView *view)
clutter_stage_view_set_dirty_projection (ClutterStageView *view,
gboolean dirty)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
priv->dirty_projection = TRUE;
}
void
clutter_stage_view_set_projection (ClutterStageView *view,
const CoglMatrix *matrix)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
priv->dirty_projection = FALSE;
clutter_stage_view_foreach_front_buffer (view,
set_framebuffer_projection_matrix,
matrix);
priv->dirty_projection = dirty;
}
void
@@ -962,6 +387,19 @@ clutter_stage_view_take_redraw_clip (ClutterStageView *view)
return g_steal_pointer (&priv->redraw_clip);
}
void
clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
gfloat *x,
gfloat *y)
{
gfloat z = 0, w = 1;
CoglMatrix matrix;
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
cogl_matrix_get_inverse (&matrix, &matrix);
cogl_matrix_transform_point (&matrix, x, y, &z, &w);
}
static void
clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view,
CoglMatrix *matrix)
@@ -969,25 +407,6 @@ clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *vie
cogl_matrix_init_identity (matrix);
}
void
clutter_stage_view_assign_next_scanout (ClutterStageView *view,
CoglScanout *scanout)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
g_set_object (&priv->next_scanout, scanout);
}
CoglScanout *
clutter_stage_view_take_scanout (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
return g_steal_pointer (&priv->next_scanout);
}
static void
clutter_stage_view_get_property (GObject *object,
guint prop_id,
@@ -1000,9 +419,6 @@ clutter_stage_view_get_property (GObject *object,
switch (prop_id)
{
case PROP_NAME:
g_value_set_string (value, priv->name);
break;
case PROP_LAYOUT:
g_value_set_boxed (value, &priv->layout);
break;
@@ -1012,8 +428,8 @@ clutter_stage_view_get_property (GObject *object,
case PROP_OFFSCREEN:
g_value_set_boxed (value, priv->offscreen);
break;
case PROP_USE_SHADOWFB:
g_value_set_boolean (value, priv->use_shadowfb);
case PROP_SHADOWFB:
g_value_set_boxed (value, priv->shadowfb);
break;
case PROP_SCALE:
g_value_set_float (value, priv->scale);
@@ -1036,9 +452,6 @@ clutter_stage_view_set_property (GObject *object,
switch (prop_id)
{
case PROP_NAME:
priv->name = g_value_dup_string (value);
break;
case PROP_LAYOUT:
layout = g_value_get_boxed (value);
priv->layout = *layout;
@@ -1063,8 +476,8 @@ clutter_stage_view_set_property (GObject *object,
case PROP_OFFSCREEN:
priv->offscreen = g_value_dup_boxed (value);
break;
case PROP_USE_SHADOWFB:
priv->use_shadowfb = g_value_get_boolean (value);
case PROP_SHADOWFB:
priv->shadowfb = g_value_dup_boxed (value);
break;
case PROP_SCALE:
priv->scale = g_value_get_float (value);
@@ -1074,41 +487,18 @@ clutter_stage_view_set_property (GObject *object,
}
}
static void
clutter_stage_view_constructed (GObject *object)
{
ClutterStageView *view = CLUTTER_STAGE_VIEW (object);
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->use_shadowfb)
init_shadowfb (view);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->constructed (object);
}
static void
clutter_stage_view_dispose (GObject *object)
{
ClutterStageView *view = CLUTTER_STAGE_VIEW (object);
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
int i;
g_clear_pointer (&priv->name, g_free);
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
g_clear_pointer (&priv->shadow.framebuffer, cogl_object_unref);
for (i = 0; i < G_N_ELEMENTS (priv->shadow.dma_buf.handles); i++)
{
g_clear_pointer (&priv->shadow.dma_buf.handles[i],
cogl_dma_buf_handle_free);
}
g_clear_pointer (&priv->shadow.dma_buf.damage_history,
clutter_damage_history_free);
g_clear_pointer (&priv->shadowfb, cogl_object_unref);
g_clear_pointer (&priv->offscreen, cogl_object_unref);
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
@@ -1135,17 +525,8 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
object_class->get_property = clutter_stage_view_get_property;
object_class->set_property = clutter_stage_view_set_property;
object_class->constructed = clutter_stage_view_constructed;
object_class->dispose = clutter_stage_view_dispose;
obj_props[PROP_NAME] =
g_param_spec_string ("name",
"Name",
"Name of view",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_LAYOUT] =
g_param_spec_boxed ("layout",
"View layout",
@@ -1173,14 +554,14 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_USE_SHADOWFB] =
g_param_spec_boolean ("use-shadowfb",
"Use shadowfb",
"Whether to use one or more shadow framebuffers",
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SHADOWFB] =
g_param_spec_boxed ("shadowfb",
"Shadow framebuffer",
"Framebuffer used as intermediate shadow buffer",
COGL_TYPE_HANDLE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SCALE] =
g_param_spec_float ("scale",

View File

@@ -43,12 +43,6 @@ struct _ClutterStageViewClass
void (* get_offscreen_transformation_matrix) (ClutterStageView *view,
CoglMatrix *matrix);
void (* transform_rect_to_onscreen) (ClutterStageView *view,
const cairo_rectangle_int_t *src_rect,
int dst_width,
int dst_height,
cairo_rectangle_int_t *dst_rect);
};
CLUTTER_EXPORT
@@ -62,6 +56,11 @@ CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view);
CLUTTER_EXPORT
void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view);
CLUTTER_EXPORT
void clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
gfloat *x,
gfloat *y);
CLUTTER_EXPORT
float clutter_stage_view_get_scale (ClutterStageView *view);

View File

@@ -142,8 +142,6 @@ struct _ClutterStagePrivate
int update_freeze_count;
gboolean needs_update;
guint redraw_pending : 1;
guint throttle_motion_events : 1;
guint min_size_changed : 1;
@@ -554,7 +552,7 @@ clutter_stage_add_redraw_clip (ClutterStage *stage,
{
GList *l;
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *view = l->data;
@@ -615,7 +613,8 @@ stage_is_default (ClutterStage *stage)
static void
clutter_stage_allocate (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
ClutterActorBox alloc = CLUTTER_ACTOR_BOX_INIT_ZERO;
@@ -623,7 +622,6 @@ clutter_stage_allocate (ClutterActor *self,
float new_width, new_height;
float width, height;
cairo_rectangle_int_t window_size;
ClutterLayoutManager *layout_manager = clutter_actor_get_layout_manager (self);
if (priv->impl == NULL)
return;
@@ -645,21 +643,15 @@ clutter_stage_allocate (ClutterActor *self,
*/
if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC))
{
ClutterActorBox children_box;
children_box.x1 = children_box.y1 = 0.f;
children_box.x2 = box->x2 - box->x1;
children_box.y2 = box->y2 - box->y1;
CLUTTER_NOTE (LAYOUT,
"Following allocation to %.2fx%.2f",
width, height);
"Following allocation to %.2fx%.2f (absolute origin %s)",
width, height,
(flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED)
? "changed"
: "not changed");
clutter_actor_set_allocation (self, box);
clutter_layout_manager_allocate (layout_manager,
CLUTTER_CONTAINER (self),
&children_box);
clutter_actor_set_allocation (self, box,
flags | CLUTTER_DELEGATE_LAYOUT);
/* Ensure the window is sized correctly */
if (priv->min_size_changed)
@@ -707,16 +699,16 @@ clutter_stage_allocate (ClutterActor *self,
CLUTTER_NOTE (LAYOUT,
"Overriding original allocation of %.2fx%.2f "
"with %.2fx%.2f",
"with %.2fx%.2f (absolute origin %s)",
width, height,
override.x2, override.y2);
override.x2, override.y2,
(flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED)
? "changed"
: "not changed");
/* and store the overridden allocation */
clutter_actor_set_allocation (self, &override);
clutter_layout_manager_allocate (layout_manager,
CLUTTER_CONTAINER (self),
&override);
clutter_actor_set_allocation (self, &override,
flags | CLUTTER_DELEGATE_LAYOUT);
}
/* reset the viewport if the allocation effectively changed */
@@ -932,8 +924,7 @@ clutter_stage_do_paint_view (ClutterStage *stage,
ClutterPaintContext *paint_context;
cairo_rectangle_int_t clip_rect;
paint_context = clutter_paint_context_new_for_view (view, redraw_clip,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_view (view, redraw_clip);
cairo_region_get_extents (redraw_clip, &clip_rect);
setup_view_for_pick_or_paint (stage, view, &clip_rect);
@@ -1178,7 +1169,7 @@ _clutter_stage_queue_event (ClutterStage *stage,
{
ClutterMasterClock *master_clock = _clutter_master_clock_get_default ();
_clutter_master_clock_start_running (master_clock);
clutter_stage_schedule_update (stage);
_clutter_stage_schedule_update (stage);
}
}
@@ -1310,9 +1301,7 @@ _clutter_stage_needs_update (ClutterStage *stage)
priv = stage->priv;
return (priv->redraw_pending ||
priv->needs_update ||
g_hash_table_size (priv->pending_relayouts) > 0);
return priv->redraw_pending || g_hash_table_size (priv->pending_relayouts) > 0;
}
void
@@ -1322,7 +1311,7 @@ clutter_stage_queue_actor_relayout (ClutterStage *stage,
ClutterStagePrivate *priv = stage->priv;
if (g_hash_table_size (priv->pending_relayouts) == 0)
clutter_stage_schedule_update (stage);
_clutter_stage_schedule_update (stage);
g_hash_table_add (priv->pending_relayouts, g_object_ref (actor));
priv->pending_relayouts_version++;
@@ -1369,7 +1358,8 @@ _clutter_stage_maybe_relayout (ClutterActor *actor)
CLUTTER_SET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
old_version = priv->pending_relayouts_version;
clutter_actor_allocate_preferred_size (queued_actor);
clutter_actor_allocate_preferred_size (queued_actor,
CLUTTER_ALLOCATION_NONE);
CLUTTER_UNSET_PRIVATE_FLAGS (queued_actor, CLUTTER_IN_RELAYOUT);
@@ -1503,8 +1493,6 @@ _clutter_stage_do_update (ClutterStage *stage)
priv->stage_was_relayout = FALSE;
priv->needs_update = FALSE;
/* if the stage is being destroyed, or if the destruction already
* happened and we don't have an StageWindow any more, then we
* should bail out
@@ -1584,7 +1572,7 @@ is_full_stage_redraw_queued (ClutterStage *stage)
{
GList *l;
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *view = l->data;
@@ -2440,7 +2428,7 @@ _clutter_stage_dirty_projection (ClutterStage *stage)
{
ClutterStageView *view = l->data;
clutter_stage_view_invalidate_projection (view);
clutter_stage_view_set_dirty_projection (view, TRUE);
}
}
@@ -2530,7 +2518,7 @@ _clutter_stage_dirty_viewport (ClutterStage *stage)
{
ClutterStageView *view = l->data;
clutter_stage_view_invalidate_viewport (view);
clutter_stage_view_set_dirty_viewport (view, TRUE);
}
}
@@ -3153,6 +3141,7 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
ClutterStageView *view)
{
ClutterStagePrivate *priv = stage->priv;
CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
if (clutter_stage_view_is_dirty_viewport (view))
{
@@ -3179,14 +3168,19 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
viewport_y = roundf (priv->viewport[1] * fb_scale - viewport_offset_y);
viewport_width = roundf (priv->viewport[2] * fb_scale);
viewport_height = roundf (priv->viewport[3] * fb_scale);
cogl_framebuffer_set_viewport (fb,
viewport_x, viewport_y,
viewport_width, viewport_height);
clutter_stage_view_set_viewport (view,
viewport_x, viewport_y,
viewport_width, viewport_height);
clutter_stage_view_set_dirty_viewport (view, FALSE);
}
if (clutter_stage_view_is_dirty_projection (view))
clutter_stage_view_set_projection (view, &priv->projection);
{
cogl_framebuffer_set_projection_matrix (fb, &priv->projection);
clutter_stage_view_set_dirty_projection (view, FALSE);
}
}
#undef _DEG_TO_RAD
@@ -3214,7 +3208,7 @@ clutter_stage_ensure_redraw (ClutterStage *stage)
priv = stage->priv;
if (!_clutter_stage_needs_update (stage))
clutter_stage_schedule_update (stage);
_clutter_stage_schedule_update (stage);
priv->redraw_pending = TRUE;
@@ -3442,13 +3436,13 @@ clutter_stage_get_minimum_size (ClutterStage *stage,
}
/**
* clutter_stage_schedule_update:
* @stage: a #ClutterStage actor
* _clutter_stage_schedule_update:
* @window: a #ClutterStage actor
*
* Schedules a redraw of the #ClutterStage at the next optimal timestamp.
*/
void
clutter_stage_schedule_update (ClutterStage *stage)
_clutter_stage_schedule_update (ClutterStage *stage)
{
ClutterStageWindow *stage_window;
@@ -3459,8 +3453,6 @@ clutter_stage_schedule_update (ClutterStage *stage)
if (stage_window == NULL)
return;
stage->priv->needs_update = TRUE;
return _clutter_stage_window_schedule_update (stage_window,
stage->priv->sync_delay);
}
@@ -3470,7 +3462,7 @@ clutter_stage_schedule_update (ClutterStage *stage)
* @stage: a #ClutterStage actor
*
* Returns the earliest time in which the stage is ready to update. The update
* time is set when clutter_stage_schedule_update() is called. This can then
* time is set when _clutter_stage_schedule_update() is called. This can then
* be used by e.g. the #ClutterMasterClock to know when the stage needs to be
* redrawn.
*
@@ -3580,7 +3572,7 @@ _clutter_stage_queue_actor_redraw (ClutterStage *stage,
CLUTTER_NOTE (PAINT, "First redraw request");
clutter_stage_schedule_update (stage);
_clutter_stage_schedule_update (stage);
priv->redraw_pending = TRUE;
master_clock = _clutter_master_clock_get_default ();
@@ -4171,97 +4163,6 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
return TRUE;
}
void
clutter_stage_paint_to_framebuffer (ClutterStage *stage,
CoglFramebuffer *framebuffer,
const cairo_rectangle_int_t *rect,
float scale,
ClutterPaintFlag paint_flags)
{
ClutterStagePrivate *priv = stage->priv;
ClutterPaintContext *paint_context;
cairo_region_t *redraw_clip;
redraw_clip = cairo_region_create_rectangle (rect);
paint_context =
clutter_paint_context_new_for_framebuffer (framebuffer,
redraw_clip,
paint_flags);
cairo_region_destroy (redraw_clip);
cogl_framebuffer_push_matrix (framebuffer);
cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection);
cogl_framebuffer_set_viewport (framebuffer,
-(rect->x * scale),
-(rect->y * scale),
priv->viewport[2] * scale,
priv->viewport[3] * scale);
clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);
cogl_framebuffer_pop_matrix (framebuffer);
clutter_paint_context_destroy (paint_context);
}
gboolean
clutter_stage_paint_to_buffer (ClutterStage *stage,
const cairo_rectangle_int_t *rect,
float scale,
uint8_t *data,
int stride,
CoglPixelFormat format,
ClutterPaintFlag paint_flags,
GError **error)
{
ClutterBackend *clutter_backend = clutter_get_default_backend ();
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
int texture_width, texture_height;
CoglTexture2D *texture;
CoglOffscreen *offscreen;
CoglFramebuffer *framebuffer;
CoglBitmap *bitmap;
texture_width = (int) ceilf (rect->width * scale);
texture_height = (int) ceilf (rect->height * scale);
texture = cogl_texture_2d_new_with_size (cogl_context,
texture_width,
texture_height);
if (!texture)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to create %dx%d texture",
texture_width, texture_height);
return FALSE;
}
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
framebuffer = COGL_FRAMEBUFFER (offscreen);
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (framebuffer, error))
return FALSE;
clutter_stage_paint_to_framebuffer (stage, framebuffer,
rect, scale, paint_flags);
bitmap = cogl_bitmap_new_for_data (cogl_context,
texture_width, texture_height,
format,
stride,
data);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
0, 0,
COGL_READ_PIXELS_COLOR_BUFFER,
bitmap);
cogl_object_unref (bitmap);
cogl_object_unref (framebuffer);
return TRUE;
}
static void
capture_view_into (ClutterStage *stage,
gboolean paint,
@@ -4409,11 +4310,8 @@ clutter_stage_thaw_updates (ClutterStage *stage)
}
}
/**
* clutter_stage_peek_stage_views: (skip)
*/
GList *
clutter_stage_peek_stage_views (ClutterStage *stage)
_clutter_stage_peek_stage_views (ClutterStage *stage)
{
ClutterStagePrivate *priv = stage->priv;

View File

@@ -209,9 +209,6 @@ CLUTTER_EXPORT
void clutter_stage_skip_sync_delay (ClutterStage *stage);
#endif
CLUTTER_EXPORT
void clutter_stage_schedule_update (ClutterStage *stage);
CLUTTER_EXPORT
gboolean clutter_stage_get_capture_final_size (ClutterStage *stage,
cairo_rectangle_int_t *rect,

View File

@@ -3037,7 +3037,8 @@ clutter_text_get_preferred_height (ClutterActor *self,
static void
clutter_text_allocate (ClutterActor *self,
const ClutterActorBox *box)
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterText *text = CLUTTER_TEXT (self);
ClutterActorClass *parent_class;
@@ -3057,7 +3058,7 @@ clutter_text_allocate (ClutterActor *self,
box->y2 - box->y1);
parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
parent_class->allocate (self, box);
parent_class->allocate (self, box, flags);
}
static gboolean
@@ -4786,11 +4787,11 @@ clutter_text_queue_redraw_or_relayout (ClutterText *self)
clutter_text_get_preferred_height (actor, preferred_width, NULL, &preferred_height);
if (clutter_actor_has_allocation (actor) &&
fabsf (preferred_width - clutter_actor_get_width (actor)) <= 0.001 &&
fabsf (preferred_height - clutter_actor_get_height (actor)) <= 0.001)
clutter_text_queue_redraw (actor);
else
(fabsf (preferred_width - clutter_actor_get_width (actor)) > 0.001 ||
fabsf (preferred_height - clutter_actor_get_height (actor)) > 0.001))
clutter_actor_queue_relayout (actor);
else
clutter_text_queue_redraw (actor);
}
static void

View File

@@ -24,6 +24,7 @@
/**
* SECTION:clutter-timeline
* @short_description: A class for time-based events
* @see_also: #ClutterAnimation, #ClutterAnimator, #ClutterState
*
* #ClutterTimeline is a base class for managing time-based event that cause
* Clutter to redraw a stage, such as animations.
@@ -70,7 +71,7 @@
* when reaching completion by using the #ClutterTimeline:auto-reverse property.
*
* Timelines are used in the Clutter animation framework by classes like
* #ClutterTransition.
* #ClutterAnimation, #ClutterAnimator, and #ClutterState.
*
* ## Defining Timelines in ClutterScript
*

View File

@@ -79,6 +79,10 @@ typedef struct _ClutterKnot ClutterKnot;
typedef struct _ClutterMargin ClutterMargin;
typedef struct _ClutterPerspective ClutterPerspective;
typedef struct _ClutterAlpha ClutterAlpha;
typedef struct _ClutterAnimation ClutterAnimation;
typedef struct _ClutterState ClutterState;
typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool;
typedef struct _ClutterInputDevice ClutterInputDevice;
typedef struct _ClutterVirtualInputDevice ClutterVirtualInputDevice;

View File

@@ -38,7 +38,6 @@
#include "clutter-actor-private.h"
#include "clutter-backend-private.h"
#include "clutter-damage-history.h"
#include "clutter-debug.h"
#include "clutter-event.h"
#include "clutter-enum-types.h"
@@ -52,9 +51,13 @@
typedef struct _ClutterStageViewCoglPrivate
{
/* Damage history, in stage view render target framebuffer coordinate space.
/*
* List of previous damaged areas in stage view framebuffer coordinate space.
*/
ClutterDamageHistory *damage_history;
#define DAMAGE_HISTORY_MAX 16
#define DAMAGE_HISTORY(x) ((x) & (DAMAGE_HISTORY_MAX - 1))
cairo_region_t * damage_history[DAMAGE_HISTORY_MAX];
unsigned int damage_index;
} ClutterStageViewCoglPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl,
@@ -285,13 +288,26 @@ clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
{
}
static inline gboolean
valid_buffer_age (ClutterStageViewCogl *view_cogl,
int age)
{
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
if (age <= 0)
return FALSE;
return age < MIN (view_priv->damage_index, DAMAGE_HISTORY_MAX);
}
static void
paint_damage_region (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region,
cairo_region_t *queued_redraw_clip)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
static CoglPipeline *overlay_blue = NULL;
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
@@ -359,29 +375,31 @@ static gboolean
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region,
gboolean swap_with_damage)
gboolean swap_with_damage,
cairo_region_t *queued_redraw_clip)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
int *damage, n_rects, i;
clutter_stage_view_before_swap_buffer (view, swap_region);
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
paint_damage_region (stage_window, view, swap_region, queued_redraw_clip);
n_rects = cairo_region_num_rectangles (swap_region);
damage = g_newa (int, n_rects * 4);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (swap_region, i, &rect);
damage[i * 4] = rect.x;
damage[i * 4 + 1] = rect.y;
damage[i * 4 + 2] = rect.width;
damage[i * 4 + 3] = rect.height;
}
if (cogl_is_onscreen (framebuffer))
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
int *damage, n_rects, i;
n_rects = cairo_region_num_rectangles (swap_region);
damage = g_newa (int, n_rects * 4);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (swap_region, i, &rect);
damage[i * 4] = rect.x;
damage[i * 4 + 1] = rect.y;
damage[i * 4 + 2] = rect.width;
damage[i * 4 + 3] = rect.height;
}
/* push on the screen */
if (n_rects > 0 && !swap_with_damage)
@@ -416,6 +434,18 @@ swap_framebuffer (ClutterStageWindow *stage_window,
}
}
static void
scale_and_clamp_rect (const graphene_rect_t *rect,
float scale,
cairo_rectangle_int_t *dest)
{
graphene_rect_t tmp = *rect;
graphene_rect_scale (&tmp, scale, scale, &tmp);
_clutter_util_rectangle_int_extents (&tmp, dest);
}
static cairo_region_t *
offset_scale_and_clamp_region (const cairo_region_t *region,
int offset_x,
@@ -437,52 +467,15 @@ offset_scale_and_clamp_region (const cairo_region_t *region,
rects = freeme = g_new (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t *rect = &rects[i];
graphene_rect_t tmp;
cairo_region_get_rectangle (region, i, rect);
_clutter_util_rect_from_rectangle (rect, &tmp);
graphene_rect_offset (&tmp, offset_x, offset_y);
graphene_rect_scale (&tmp, scale, scale, &tmp);
_clutter_util_rectangle_int_extents (&tmp, rect);
}
return cairo_region_create_rectangles (rects, n_rects);
}
static cairo_region_t *
scale_offset_and_clamp_region (const cairo_region_t *region,
float scale,
int offset_x,
int offset_y)
{
int n_rects, i;
cairo_rectangle_int_t *rects;
g_autofree cairo_rectangle_int_t *freeme = NULL;
n_rects = cairo_region_num_rectangles (region);
if (n_rects == 0)
return cairo_region_create ();
if (n_rects < MAX_STACK_RECTS)
rects = g_newa (cairo_rectangle_int_t, n_rects);
else
rects = freeme = g_new (cairo_rectangle_int_t, n_rects);
cairo_region_get_rectangle (region, i, &rects[i]);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t *rect = &rects[i];
graphene_rect_t tmp;
cairo_region_get_rectangle (region, i, rect);
_clutter_util_rect_from_rectangle (rect, &tmp);
graphene_rect_scale (&tmp, scale, scale, &tmp);
_clutter_util_rect_from_rectangle (&rects[i], &tmp);
graphene_rect_offset (&tmp, offset_x, offset_y);
_clutter_util_rectangle_int_extents (&tmp, rect);
scale_and_clamp_rect (&tmp, scale, &rects[i]);
}
return cairo_region_create_rectangles (rects, n_rects);
@@ -498,38 +491,107 @@ paint_stage (ClutterStageCogl *stage_cogl,
_clutter_stage_maybe_setup_viewport (stage, view);
clutter_stage_paint_view (stage, view, redraw_clip);
clutter_stage_view_after_paint (view, redraw_clip);
clutter_stage_view_after_paint (view);
}
static void
fill_current_damage_history (ClutterStageView *view,
cairo_region_t *damage)
{
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
cairo_region_t **current_fb_damage;
current_fb_damage =
&view_priv->damage_history[DAMAGE_HISTORY (view_priv->damage_index)];
g_clear_pointer (current_fb_damage, cairo_region_destroy);
*current_fb_damage = cairo_region_copy (damage);
view_priv->damage_index++;
}
static void
fill_current_damage_history_rectangle (ClutterStageView *view,
const cairo_rectangle_int_t *rect)
{
cairo_region_t *damage;
damage = cairo_region_create_rectangle (rect);
fill_current_damage_history (view, damage);
cairo_region_destroy (damage);
}
static cairo_region_t *
transform_swap_region_to_onscreen (ClutterStageView *view,
cairo_region_t *swap_region)
{
CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
CoglFramebuffer *framebuffer;
cairo_rectangle_int_t layout;
gint width, height;
int n_rects, i;
cairo_rectangle_int_t *rects;
cairo_region_t *transformed_region;
int width, height;
width = cogl_framebuffer_get_width (onscreen);
height = cogl_framebuffer_get_height (onscreen);
framebuffer = clutter_stage_view_get_onscreen (view);
clutter_stage_view_get_layout (view, &layout);
width = cogl_framebuffer_get_width (framebuffer);
height = cogl_framebuffer_get_height (framebuffer);
n_rects = cairo_region_num_rectangles (swap_region);
rects = g_newa (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
gfloat x1, y1, x2, y2;
cairo_region_get_rectangle (swap_region, i, &rects[i]);
clutter_stage_view_transform_rect_to_onscreen (view,
&rects[i],
width,
height,
&rects[i]);
x1 = (float) rects[i].x / layout.width;
y1 = (float) rects[i].y / layout.height;
x2 = (float) (rects[i].x + rects[i].width) / layout.width;
y2 = (float) (rects[i].y + rects[i].height) / layout.height;
clutter_stage_view_transform_to_onscreen (view, &x1, &y1);
clutter_stage_view_transform_to_onscreen (view, &x2, &y2);
x1 = floor (x1 * width);
y1 = floor (height - (y1 * height));
x2 = ceil (x2 * width);
y2 = ceil (height - (y2 * height));
rects[i].x = x1;
rects[i].y = y1;
rects[i].width = x2 - x1;
rects[i].height = y2 - y1;
}
transformed_region = cairo_region_create_rectangles (rects, n_rects);
return transformed_region;
}
static void
calculate_scissor_region (cairo_rectangle_int_t *fb_clip_region,
int subpixel_compensation,
int fb_width,
int fb_height,
cairo_rectangle_int_t *out_scissor_rect)
{
*out_scissor_rect = *fb_clip_region;
if (subpixel_compensation == 0)
return;
if (fb_clip_region->x > 0)
out_scissor_rect->x += subpixel_compensation;
if (fb_clip_region->y > 0)
out_scissor_rect->y += subpixel_compensation;
if (fb_clip_region->x + fb_clip_region->width < fb_width)
out_scissor_rect->width -= 2 * subpixel_compensation;
if (fb_clip_region->y + fb_clip_region->height < fb_height)
out_scissor_rect->height -= 2 * subpixel_compensation;
}
static inline gboolean
is_buffer_age_enabled (void)
{
@@ -548,21 +610,27 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view);
CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (view);
cairo_rectangle_int_t view_rect;
gboolean is_full_redraw;
gboolean may_use_clipped_redraw;
gboolean use_clipped_redraw;
gboolean can_blit_sub_buffer;
gboolean has_buffer_age;
gboolean do_swap_buffer;
gboolean swap_with_damage;
ClutterActor *wrapper;
cairo_region_t *redraw_clip;
cairo_region_t *queued_redraw_clip = NULL;
cairo_region_t *queued_redraw_clip;
cairo_region_t *fb_clip_region;
cairo_region_t *swap_region;
cairo_rectangle_int_t redraw_rect;
gboolean clip_region_empty;
float fb_scale;
int subpixel_compensation = 0;
int fb_width, fb_height;
int buffer_age;
gboolean res;
wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
clutter_stage_view_get_layout (view, &view_rect);
fb_scale = clutter_stage_view_get_scale (view);
@@ -570,14 +638,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
fb_height = cogl_framebuffer_get_height (fb);
can_blit_sub_buffer =
cogl_is_onscreen (onscreen) &&
cogl_is_onscreen (fb) &&
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION);
has_buffer_age = cogl_is_onscreen (onscreen) && is_buffer_age_enabled ();
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
redraw_clip = clutter_stage_view_take_redraw_clip (view);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION))
queued_redraw_clip = cairo_region_copy (redraw_clip);
/* NB: a NULL redraw clip == full stage redraw */
if (!redraw_clip)
@@ -585,35 +651,51 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
else
is_full_redraw = FALSE;
if (has_buffer_age)
{
buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (onscreen));
if (!clutter_damage_history_is_age_valid (view_priv->damage_history,
buffer_age))
{
CLUTTER_NOTE (CLIPPING,
"Invalid back buffer(age=%d): forcing full redraw\n",
buffer_age);
use_clipped_redraw = FALSE;
}
}
use_clipped_redraw =
use_clipped_redraw &&
!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
may_use_clipped_redraw =
_clutter_stage_window_can_clip_redraws (stage_window) &&
(can_blit_sub_buffer || has_buffer_age) &&
!is_full_redraw &&
/* some drivers struggle to get going and produce some junk
* frames when starting up... */
cogl_onscreen_get_frame_counter (COGL_ONSCREEN (onscreen)) > 3;
cogl_onscreen_get_frame_counter (COGL_ONSCREEN (fb)) > 3;
if (use_clipped_redraw)
if (has_buffer_age)
{
buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (fb));
if (!valid_buffer_age (view_cogl, buffer_age))
{
CLUTTER_NOTE (CLIPPING, "Invalid back buffer(age=%d): forcing full redraw\n", buffer_age);
may_use_clipped_redraw = FALSE;
}
}
if (may_use_clipped_redraw)
{
fb_clip_region = offset_scale_and_clamp_region (redraw_clip,
-view_rect.x,
-view_rect.y,
fb_scale);
if (fb_scale != floorf (fb_scale))
{
int n_rects, i;
cairo_rectangle_int_t *rects;
subpixel_compensation = ceilf (fb_scale);
n_rects = cairo_region_num_rectangles (fb_clip_region);
rects = g_newa (cairo_rectangle_int_t, n_rects);
for (i = 0; i < n_rects; i++)
{
cairo_region_get_rectangle (fb_clip_region, i, &rects[i]);
rects[i].x -= subpixel_compensation;
rects[i].y -= subpixel_compensation;
rects[i].width += 2 * subpixel_compensation;
rects[i].height += 2 * subpixel_compensation;
}
cairo_region_destroy (fb_clip_region);
fb_clip_region = cairo_region_create_rectangles (rects, n_rects);
}
}
else
{
@@ -629,40 +711,48 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
redraw_clip = cairo_region_create_rectangle (&view_rect);
}
g_return_val_if_fail (!cairo_region_is_empty (fb_clip_region), FALSE);
queued_redraw_clip = cairo_region_copy (redraw_clip);
if (may_use_clipped_redraw &&
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
use_clipped_redraw = TRUE;
else
use_clipped_redraw = FALSE;
clip_region_empty = may_use_clipped_redraw && cairo_region_is_empty (fb_clip_region);
swap_with_damage = FALSE;
if (has_buffer_age)
{
clutter_damage_history_record (view_priv->damage_history,
fb_clip_region);
if (use_clipped_redraw)
if (use_clipped_redraw && !clip_region_empty)
{
cairo_region_t *fb_damage;
cairo_region_t *view_damage;
int age;
int i;
fill_current_damage_history (view, fb_clip_region);
fb_damage = cairo_region_create ();
for (age = 1; age <= buffer_age; age++)
for (i = 1; i <= buffer_age; i++)
{
const cairo_region_t *old_damage;
int damage_index;
old_damage =
clutter_damage_history_lookup (view_priv->damage_history, age);
cairo_region_union (fb_damage, old_damage);
damage_index = DAMAGE_HISTORY (view_priv->damage_index - i - 1);
cairo_region_union (fb_damage,
view_priv->damage_history[damage_index]);
}
/* Update the fb clip region with the extra damage. */
cairo_region_union (fb_clip_region, fb_damage);
/* Update the redraw clip with the extra damage done to the view */
view_damage = scale_offset_and_clamp_region (fb_damage,
1.0f / fb_scale,
view_rect.x,
view_rect.y);
view_damage = offset_scale_and_clamp_region (fb_damage,
0, 0,
1.0f / fb_scale);
cairo_region_translate (view_damage, view_rect.x, view_rect.y);
cairo_region_intersect_rectangle (view_damage, &view_rect);
/* Update the redraw clip region with the extra damage. */
cairo_region_union (redraw_clip, view_damage);
cairo_region_destroy (view_damage);
@@ -674,13 +764,55 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
swap_with_damage = TRUE;
}
else if (!use_clipped_redraw)
{
cairo_rectangle_int_t fb_damage;
clutter_damage_history_step (view_priv->damage_history);
fb_damage = (cairo_rectangle_int_t) {
.x = 0,
.y = 0,
.width = ceilf (view_rect.width * fb_scale),
.height = ceilf (view_rect.height * fb_scale)
};
fill_current_damage_history_rectangle (view, &fb_damage);
}
}
if (use_clipped_redraw)
if (use_clipped_redraw && clip_region_empty)
{
cogl_framebuffer_push_region_clip (fb, fb_clip_region);
CLUTTER_NOTE (CLIPPING, "Empty stage output paint\n");
}
else if (use_clipped_redraw)
{
cairo_rectangle_int_t clip_rect;
cairo_rectangle_int_t scissor_rect;
if (cairo_region_num_rectangles (fb_clip_region) == 1)
{
cairo_region_get_extents (fb_clip_region, &clip_rect);
calculate_scissor_region (&clip_rect,
subpixel_compensation,
fb_width, fb_height,
&scissor_rect);
CLUTTER_NOTE (CLIPPING,
"Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
scissor_rect.x,
scissor_rect.y,
scissor_rect.width,
scissor_rect.height);
cogl_framebuffer_push_scissor_clip (fb,
scissor_rect.x,
scissor_rect.y,
scissor_rect.width,
scissor_rect.height);
}
else
{
cogl_framebuffer_push_region_clip (fb, fb_clip_region);
}
paint_stage (stage_cogl, view, redraw_clip);
@@ -690,7 +822,77 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
{
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
paint_stage (stage_cogl, view, redraw_clip);
/* If we are trying to debug redraw issues then we want to pass
* the redraw_clip so it can be visualized */
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
may_use_clipped_redraw &&
!clip_region_empty)
{
cairo_rectangle_int_t clip_rect;
cairo_rectangle_int_t scissor_rect;
cairo_region_get_extents (fb_clip_region, &clip_rect);
calculate_scissor_region (&clip_rect,
subpixel_compensation,
fb_width, fb_height,
&scissor_rect);
cogl_framebuffer_push_scissor_clip (fb,
scissor_rect.x,
scissor_rect.y,
scissor_rect.width,
scissor_rect.height);
paint_stage (stage_cogl, view, redraw_clip);
cogl_framebuffer_pop_clip (fb);
}
else
{
paint_stage (stage_cogl, view, redraw_clip);
}
}
cairo_region_get_extents (redraw_clip, &redraw_rect);
if (may_use_clipped_redraw &&
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
{
CoglContext *ctx = cogl_framebuffer_get_context (fb);
static CoglPipeline *outline = NULL;
ClutterActor *actor = CLUTTER_ACTOR (wrapper);
float x_1 = redraw_rect.x;
float x_2 = redraw_rect.x + redraw_rect.width;
float y_1 = redraw_rect.y;
float y_2 = redraw_rect.y + redraw_rect.height;
CoglVertexP2 quad[4] = {
{ x_1, y_1 },
{ x_2, y_1 },
{ x_2, y_2 },
{ x_1, y_2 }
};
CoglPrimitive *prim;
CoglMatrix modelview;
if (outline == NULL)
{
outline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color4ub (outline, 0xff, 0x00, 0x00, 0xff);
}
prim = cogl_primitive_new_p2 (ctx,
COGL_VERTICES_MODE_LINE_LOOP,
4, /* n_vertices */
quad);
cogl_framebuffer_push_matrix (fb);
cogl_matrix_init_identity (&modelview);
_clutter_actor_apply_modelview_transform (actor, &modelview);
cogl_framebuffer_set_modelview_matrix (fb, &modelview);
cogl_framebuffer_draw_primitive (fb, outline, prim);
cogl_framebuffer_pop_matrix (fb);
cogl_object_unref (prim);
}
/* XXX: It seems there will be a race here in that the stage
@@ -702,56 +904,59 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
* artefacts.
*/
if (use_clipped_redraw)
swap_region = cairo_region_copy (fb_clip_region);
{
if (clip_region_empty)
{
do_swap_buffer = FALSE;
}
else
{
swap_region = cairo_region_copy (fb_clip_region);
do_swap_buffer = TRUE;
}
}
else
swap_region = cairo_region_create ();
{
swap_region = cairo_region_create ();
do_swap_buffer = TRUE;
}
g_clear_pointer (&redraw_clip, cairo_region_destroy);
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
g_clear_pointer (&fb_clip_region, cairo_region_destroy);
COGL_TRACE_BEGIN_SCOPED (ClutterStageCoglRedrawViewSwapFramebuffer,
"Paint (swap framebuffer)");
if (clutter_stage_view_get_onscreen (view) !=
clutter_stage_view_get_framebuffer (view))
if (do_swap_buffer)
{
cairo_region_t *transformed_swap_region;
gboolean res;
COGL_TRACE_BEGIN_SCOPED (ClutterStageCoglRedrawViewSwapFramebuffer,
"Paint (swap framebuffer)");
if (clutter_stage_view_get_onscreen (view) !=
clutter_stage_view_get_framebuffer (view))
{
cairo_region_t *transformed_swap_region;
transformed_swap_region =
transform_swap_region_to_onscreen (view, swap_region);
cairo_region_destroy (swap_region);
swap_region = transformed_swap_region;
}
res = swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage,
queued_redraw_clip);
transformed_swap_region =
transform_swap_region_to_onscreen (view, swap_region);
cairo_region_destroy (swap_region);
swap_region = transformed_swap_region;
}
if (queued_redraw_clip)
return res;
}
else
{
paint_damage_region (stage_window, view,
swap_region, queued_redraw_clip);
cairo_region_destroy (queued_redraw_clip);
return FALSE;
}
res = swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage);
cairo_region_destroy (swap_region);
return res;
}
static void
clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl,
ClutterStageView *view,
CoglScanout *scanout)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
CoglOnscreen *onscreen;
g_return_if_fail (cogl_is_onscreen (framebuffer));
onscreen = COGL_ONSCREEN (framebuffer);
cogl_onscreen_direct_scanout (onscreen, scanout);
}
static void
@@ -766,23 +971,11 @@ clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next)
{
ClutterStageView *view = l->data;
g_autoptr (CoglScanout) scanout = NULL;
if (!clutter_stage_view_has_redraw_clip (view))
continue;
scanout = clutter_stage_view_take_scanout (view);
if (scanout)
{
clutter_stage_cogl_scanout_view (stage_cogl,
view,
scanout);
swap_event = TRUE;
}
else
{
swap_event |= clutter_stage_cogl_redraw_view (stage_window, view);
}
swap_event |= clutter_stage_cogl_redraw_view (stage_window, view);
}
_clutter_stage_emit_after_paint (stage_cogl->wrapper);
@@ -862,31 +1055,12 @@ _clutter_stage_cogl_init (ClutterStageCogl *stage)
stage->update_time = -1;
}
static void
clutter_stage_view_cogl_finalize (GObject *object)
{
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (object);
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
clutter_damage_history_free (view_priv->damage_history);
G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->finalize (object);
}
static void
clutter_stage_view_cogl_init (ClutterStageViewCogl *view_cogl)
{
ClutterStageViewCoglPrivate *view_priv =
clutter_stage_view_cogl_get_instance_private (view_cogl);
view_priv->damage_history = clutter_damage_history_new ();
}
static void
clutter_stage_view_cogl_class_init (ClutterStageViewCoglClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = clutter_stage_view_cogl_finalize;
}

View File

@@ -0,0 +1,819 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
* Tomas Frydrych <tf@openedhand.com>
*
* Copyright (C) 2006, 2007, 2008 OpenedHand
* 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-alpha
* @short_description: A class for calculating a value as a function of time
*
* #ClutterAlpha is a class for calculating an floating point value
* dependent only on the position of a #ClutterTimeline.
*
* For newly written code, it is recommended to use the
* #ClutterTimeline:progress-mode property of #ClutterTimeline, or the
* clutter_timeline_set_progress_func() function instead of #ClutterAlpha.
* The #ClutterAlpha class will be deprecated in the future, and will not
* be available any more in the next major version of Clutter.
*
* A #ClutterAlpha binds a #ClutterTimeline to a progress function which
* translates the time T into an adimensional factor alpha.
*
* You should provide a #ClutterTimeline and bind it to the #ClutterAlpha
* instance using clutter_alpha_set_timeline(). You should also set an
* "animation mode", by using the #ClutterAnimationMode values that
* Clutter provides.
*
* Instead of a #ClutterAnimationMode you may provide a function returning
* the alpha value depending on the progress of the timeline, using
* clutter_alpha_set_func() or clutter_alpha_set_closure(). The alpha
* function will be executed each time a new frame in the #ClutterTimeline
* is reached.
*
* Since the alpha function is controlled by the timeline instance, you can
* pause, stop or resume the #ClutterAlpha from calling the alpha function by
* using the appropriate functions of the #ClutterTimeline object.
*
* #ClutterAlpha is available since Clutter 0.2.
*
* #ClutterAlpha is deprecated since Clutter 1.12. #ClutterTimeline and
* the #ClutterTimeline:progress-mode property replace this whole class.
*
* ## ClutterAlpha custom properties for #ClutterScript
*
* #ClutterAlpha defines a custom `function` property for
* #ClutterScript which allows to reference a custom alpha function
* available in the source code. Setting the `function` property
* is equivalent to calling clutter_alpha_set_func() with the
* specified function name. No user data or #GDestroyNotify is
* available to be passed.
*
* The following JSON fragment defines a #ClutterAlpha
* using a #ClutterTimeline with id "sine-timeline" and an alpha
* function called `my_sine_alpha`.
*
* |[
* {
* "id" : "sine-alpha",
* "timeline" : {
* "id" : "sine-timeline",
* "duration" : 500,
* "loop" : true
* },
* "function" : "my_sine_alpha"
* }
* ]|
*/
#include "clutter-build-config.h"
#include <math.h>
#include <gmodule.h>
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
#include "clutter-alpha.h"
#include "clutter-debug.h"
#include "clutter-enum-types.h"
#include "clutter-easing.h"
#include "clutter-main.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-scriptable.h"
#include "clutter-script-private.h"
struct _ClutterAlphaPrivate
{
ClutterTimeline *timeline;
guint timeline_new_frame_id;
gdouble alpha;
GClosure *closure;
ClutterAlphaFunc func;
gpointer user_data;
GDestroyNotify notify;
gulong mode;
};
enum
{
PROP_0,
PROP_TIMELINE,
PROP_ALPHA,
PROP_MODE,
PROP_LAST
};
static GParamSpec *obj_props[PROP_LAST];
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterAlpha,
clutter_alpha,
G_TYPE_INITIALLY_UNOWNED,
G_ADD_PRIVATE (ClutterAlpha)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
clutter_scriptable_iface_init));
static void
timeline_new_frame_cb (ClutterTimeline *timeline,
guint msecs,
ClutterAlpha *alpha)
{
ClutterAlphaPrivate *priv = alpha->priv;
/* Update alpha value and notify */
priv->alpha = clutter_alpha_get_alpha (alpha);
g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_ALPHA]);
}
static void
clutter_alpha_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ClutterAlpha *alpha = CLUTTER_ALPHA (object);
switch (prop_id)
{
case PROP_TIMELINE:
clutter_alpha_set_timeline (alpha, g_value_get_object (value));
break;
case PROP_MODE:
clutter_alpha_set_mode (alpha, g_value_get_ulong (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_alpha_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ClutterAlphaPrivate *priv = CLUTTER_ALPHA (object)->priv;
switch (prop_id)
{
case PROP_TIMELINE:
g_value_set_object (value, priv->timeline);
break;
case PROP_ALPHA:
g_value_set_double (value, priv->alpha);
break;
case PROP_MODE:
g_value_set_ulong (value, priv->mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
clutter_alpha_finalize (GObject *object)
{
ClutterAlphaPrivate *priv = CLUTTER_ALPHA (object)->priv;
if (priv->notify != NULL)
priv->notify (priv->user_data);
else if (priv->closure != NULL)
g_closure_unref (priv->closure);
G_OBJECT_CLASS (clutter_alpha_parent_class)->finalize (object);
}
static void
clutter_alpha_dispose (GObject *object)
{
ClutterAlpha *self = CLUTTER_ALPHA(object);
clutter_alpha_set_timeline (self, NULL);
G_OBJECT_CLASS (clutter_alpha_parent_class)->dispose (object);
}
static ClutterAlphaFunc
resolve_alpha_func (const gchar *name)
{
static GModule *module = NULL;
ClutterAlphaFunc func;
CLUTTER_NOTE (SCRIPT, "Looking up '%s' alpha function", name);
if (G_UNLIKELY (module == NULL))
module = g_module_open (NULL, 0);
if (g_module_symbol (module, name, (gpointer) &func))
{
CLUTTER_NOTE (SCRIPT, "Found '%s' alpha function in the symbols table",
name);
return func;
}
return NULL;
}
static void
clutter_alpha_set_custom_property (ClutterScriptable *scriptable,
ClutterScript *script,
const gchar *name,
const GValue *value)
{
if (strncmp (name, "function", 8) == 0)
{
g_assert (G_VALUE_HOLDS (value, G_TYPE_POINTER));
if (g_value_get_pointer (value) != NULL)
{
clutter_alpha_set_func (CLUTTER_ALPHA (scriptable),
g_value_get_pointer (value),
NULL, NULL);
}
}
else
g_object_set_property (G_OBJECT (scriptable), name, value);
}
static gboolean
clutter_alpha_parse_custom_node (ClutterScriptable *scriptable,
ClutterScript *script,
GValue *value,
const gchar *name,
JsonNode *node)
{
if (strncmp (name, "function", 8) == 0)
{
const gchar *func_name = json_node_get_string (node);
g_value_init (value, G_TYPE_POINTER);
g_value_set_pointer (value, resolve_alpha_func (func_name));
return TRUE;
}
/* we need to do this because we use gulong in place
* of ClutterAnimationMode for ClutterAlpha:mode
*/
if (strncmp (name, "mode", 4) == 0)
{
gulong mode;
mode = _clutter_script_resolve_animation_mode (node);
g_value_init (value, G_TYPE_ULONG);
g_value_set_ulong (value, mode);
return TRUE;
}
return FALSE;
}
static void
clutter_scriptable_iface_init (ClutterScriptableIface *iface)
{
iface->parse_custom_node = clutter_alpha_parse_custom_node;
iface->set_custom_property = clutter_alpha_set_custom_property;
}
static void
clutter_alpha_class_init (ClutterAlphaClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = clutter_alpha_set_property;
object_class->get_property = clutter_alpha_get_property;
object_class->finalize = clutter_alpha_finalize;
object_class->dispose = clutter_alpha_dispose;
/**
* ClutterAlpha:timeline:
*
* A #ClutterTimeline instance used to drive the alpha function.
*
* Since: 0.2
*
* Deprecated: 1.12
*/
obj_props[PROP_TIMELINE] =
g_param_spec_object ("timeline",
P_("Timeline"),
P_("Timeline used by the alpha"),
CLUTTER_TYPE_TIMELINE,
CLUTTER_PARAM_READWRITE);
/**
* ClutterAlpha:alpha:
*
* The alpha value as computed by the alpha function. The linear
* interval is 0.0 to 1.0, but the Alpha allows overshooting by
* one unit in each direction, so the valid interval is -1.0 to 2.0.
*
* Since: 0.2
* Deprecated: 1.12: Use #ClutterTimeline::new-frame and
* clutter_timeline_get_progress() instead
*/
obj_props[PROP_ALPHA] =
g_param_spec_double ("alpha",
P_("Alpha value"),
P_("Alpha value as computed by the alpha"),
-1.0, 2.0,
0.0,
CLUTTER_PARAM_READABLE);
/**
* ClutterAlpha:mode:
*
* The progress function logical id - a value from the
* #ClutterAnimationMode enumeration.
*
* If %CLUTTER_CUSTOM_MODE is used then the function set using
* clutter_alpha_set_closure() or clutter_alpha_set_func()
* will be used.
*
* Since: 1.0
* Deprecated: 1.12: Use #ClutterTimeline:progress-mode
*/
obj_props[PROP_MODE] =
g_param_spec_ulong ("mode",
P_("Mode"),
P_("Progress mode"),
0, G_MAXULONG,
CLUTTER_CUSTOM_MODE,
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
g_object_class_install_properties (object_class,
PROP_LAST,
obj_props);
}
static void
clutter_alpha_init (ClutterAlpha *self)
{
self->priv = clutter_alpha_get_instance_private (self);
self->priv->mode = CLUTTER_CUSTOM_MODE;
self->priv->alpha = 0.0;
}
/**
* clutter_alpha_get_alpha:
* @alpha: A #ClutterAlpha
*
* Query the current alpha value.
*
* Return Value: The current alpha value for the alpha
*
* Since: 0.2
*
* Deprecated: 1.12: Use clutter_timeline_get_progress()
*/
gdouble
clutter_alpha_get_alpha (ClutterAlpha *alpha)
{
ClutterAlphaPrivate *priv;
gdouble retval = 0;
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), 0);
priv = alpha->priv;
if (G_LIKELY (priv->func))
{
return priv->func (alpha, priv->user_data);
}
else if (priv->closure)
{
GValue params = G_VALUE_INIT;
GValue result_value = G_VALUE_INIT;
g_object_ref (alpha);
g_value_init (&result_value, G_TYPE_DOUBLE);
g_value_init (&params, CLUTTER_TYPE_ALPHA);
g_value_set_object (&params, alpha);
g_closure_invoke (priv->closure, &result_value, 1, &params, NULL);
retval = g_value_get_double (&result_value);
g_value_unset (&result_value);
g_value_unset (&params);
g_object_unref (alpha);
}
return retval;
}
/*
* clutter_alpha_set_closure_internal:
* @alpha: a #ClutterAlpha
* @closure: a #GClosure
*
* Sets the @closure for @alpha. This function does not
* set the #ClutterAlpha:mode property and does not emit
* the #GObject::notify signal for it.
*/
static inline void
clutter_alpha_set_closure_internal (ClutterAlpha *alpha,
GClosure *closure)
{
ClutterAlphaPrivate *priv = alpha->priv;
if (priv->notify != NULL)
priv->notify (priv->user_data);
else if (priv->closure != NULL)
g_closure_unref (priv->closure);
priv->func = NULL;
priv->user_data = NULL;
priv->notify = NULL;
if (closure == NULL)
return;
/* need to take ownership of the closure before sinking it */
priv->closure = g_closure_ref (closure);
g_closure_sink (closure);
/* set the marshaller */
if (G_CLOSURE_NEEDS_MARSHAL (closure))
{
GClosureMarshal marshal = _clutter_marshal_DOUBLE__VOID;
g_closure_set_marshal (priv->closure, marshal);
}
}
/**
* clutter_alpha_set_closure:
* @alpha: A #ClutterAlpha
* @closure: A #GClosure
*
* Sets the #GClosure used to compute the alpha value at each
* frame of the #ClutterTimeline bound to @alpha.
*
* Since: 0.8
*
* Deprecated: 1.12: Use clutter_timeline_set_progress_func()
*/
void
clutter_alpha_set_closure (ClutterAlpha *alpha,
GClosure *closure)
{
ClutterAlphaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
g_return_if_fail (closure != NULL);
priv = alpha->priv;
clutter_alpha_set_closure_internal (alpha, closure);
priv->mode = CLUTTER_CUSTOM_MODE;
g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_MODE]);
}
/**
* clutter_alpha_set_func:
* @alpha: A #ClutterAlpha
* @func: A #ClutterAlphaFunc
* @data: user data to be passed to the alpha function, or %NULL
* @destroy: notify function used when disposing the alpha function
*
* Sets the #ClutterAlphaFunc function used to compute
* the alpha value at each frame of the #ClutterTimeline
* bound to @alpha.
*
* This function will not register @func as a global alpha function.
*
* Since: 0.2
*
* Deprecated: 1.12: Use clutter_timeline_set_progress_func()
*/
void
clutter_alpha_set_func (ClutterAlpha *alpha,
ClutterAlphaFunc func,
gpointer data,
GDestroyNotify destroy)
{
ClutterAlphaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
g_return_if_fail (func != NULL);
priv = alpha->priv;
if (priv->notify != NULL)
{
priv->notify (priv->user_data);
}
else if (priv->closure != NULL)
{
g_closure_unref (priv->closure);
priv->closure = NULL;
}
priv->func = func;
priv->user_data = data;
priv->notify = destroy;
priv->mode = CLUTTER_CUSTOM_MODE;
g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_MODE]);
}
/**
* clutter_alpha_set_timeline:
* @alpha: A #ClutterAlpha
* @timeline: A #ClutterTimeline
*
* Binds @alpha to @timeline.
*
* Since: 0.2
*
* Deprecated: 1.12: Use #ClutterTimeline directly
*/
void
clutter_alpha_set_timeline (ClutterAlpha *alpha,
ClutterTimeline *timeline)
{
ClutterAlphaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
g_return_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline));
priv = alpha->priv;
if (priv->timeline == timeline)
return;
if (priv->timeline)
{
g_signal_handlers_disconnect_by_func (priv->timeline,
timeline_new_frame_cb,
alpha);
g_object_unref (priv->timeline);
priv->timeline = NULL;
}
if (timeline)
{
priv->timeline = g_object_ref (timeline);
g_signal_connect (priv->timeline, "new-frame",
G_CALLBACK (timeline_new_frame_cb),
alpha);
}
g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_TIMELINE]);
}
/**
* clutter_alpha_get_timeline:
* @alpha: A #ClutterAlpha
*
* Gets the #ClutterTimeline bound to @alpha.
*
* Return value: (transfer none): a #ClutterTimeline instance
*
* Since: 0.2
*
* Deprecated: 1.12: Use #ClutterTimeline directlry
*/
ClutterTimeline *
clutter_alpha_get_timeline (ClutterAlpha *alpha)
{
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), NULL);
return alpha->priv->timeline;
}
/**
* clutter_alpha_new:
*
* Creates a new #ClutterAlpha instance. You must set a function
* to compute the alpha value using clutter_alpha_set_func() and
* bind a #ClutterTimeline object to the #ClutterAlpha instance
* using clutter_alpha_set_timeline().
*
* Return value: the newly created empty #ClutterAlpha instance.
*
* Since: 0.2
*
* Deprecated: 1.12: Use #ClutterTimeline instead
*/
ClutterAlpha *
clutter_alpha_new (void)
{
return g_object_new (CLUTTER_TYPE_ALPHA, NULL);
}
/**
* clutter_alpha_new_full:
* @timeline: #ClutterTimeline timeline
* @mode: animation mode
*
* Creates a new #ClutterAlpha instance and sets the timeline
* and animation mode.
*
* See also clutter_alpha_set_timeline() and clutter_alpha_set_mode().
*
* Return Value: the newly created #ClutterAlpha
*
* Since: 1.0
*
* Deprecated: 1.12: Use #ClutterTimeline instead
*/
ClutterAlpha *
clutter_alpha_new_full (ClutterTimeline *timeline,
gulong mode)
{
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL);
g_return_val_if_fail (mode != CLUTTER_ANIMATION_LAST, NULL);
return g_object_new (CLUTTER_TYPE_ALPHA,
"timeline", timeline,
"mode", mode,
NULL);
}
/**
* clutter_alpha_get_mode:
* @alpha: a #ClutterAlpha
*
* Retrieves the #ClutterAnimationMode used by @alpha.
*
* Return value: the animation mode
*
* Since: 1.0
*
* Deprecated: 1.12: Use #ClutterTimeline instead
*/
gulong
clutter_alpha_get_mode (ClutterAlpha *alpha)
{
g_return_val_if_fail (CLUTTER_IS_ALPHA (alpha), CLUTTER_CUSTOM_MODE);
return alpha->priv->mode;
}
typedef struct _AlphaData {
guint closure_set : 1;
ClutterAlphaFunc func;
gpointer data;
GClosure *closure;
} AlphaData;
static GPtrArray *clutter_alphas = NULL;
static gdouble
clutter_alpha_easing_func (ClutterAlpha *alpha,
gpointer data G_GNUC_UNUSED)
{
ClutterAlphaPrivate *priv = alpha->priv;
ClutterTimeline *timeline = priv->timeline;
gdouble t, d;
if (G_UNLIKELY (priv->timeline == NULL))
return 0.0;
t = clutter_timeline_get_elapsed_time (timeline);
d = clutter_timeline_get_duration (timeline);
return clutter_easing_for_mode (priv->mode, t, d);
}
/**
* clutter_alpha_set_mode:
* @alpha: a #ClutterAlpha
* @mode: a #ClutterAnimationMode
*
* Sets the progress function of @alpha using the symbolic value
* of @mode, as taken by the #ClutterAnimationMode enumeration.
*
* Since: 1.0
*
* Deprecated: 1.12: Use #ClutterTimeline and
* clutter_timeline_set_progress_mode() instead
*/
void
clutter_alpha_set_mode (ClutterAlpha *alpha,
gulong mode)
{
ClutterAlphaPrivate *priv;
g_return_if_fail (CLUTTER_IS_ALPHA (alpha));
g_return_if_fail (mode != CLUTTER_ANIMATION_LAST);
priv = alpha->priv;
if (mode == CLUTTER_CUSTOM_MODE)
{
priv->mode = mode;
}
else if (mode < CLUTTER_ANIMATION_LAST)
{
if (priv->mode == mode)
return;
/* sanity check to avoid getting an out of sync
* enum/function mapping
*/
g_assert (clutter_get_easing_func_for_mode (mode) != NULL);
clutter_alpha_set_closure_internal (alpha, NULL);
priv->mode = mode;
CLUTTER_NOTE (ANIMATION, "New easing mode '%s'[%lu]\n",
clutter_get_easing_name_for_mode (priv->mode),
priv->mode);
priv->func = clutter_alpha_easing_func;
priv->user_data = NULL;
priv->notify = NULL;
}
else if (mode > CLUTTER_ANIMATION_LAST)
{
AlphaData *alpha_data = NULL;
gulong real_index = 0;
if (priv->mode == mode)
return;
if (G_UNLIKELY (clutter_alphas == NULL))
{
g_warning ("No alpha functions defined for ClutterAlpha to use. ");
return;
}
real_index = mode - CLUTTER_ANIMATION_LAST - 1;
alpha_data = g_ptr_array_index (clutter_alphas, real_index);
if (G_UNLIKELY (alpha_data == NULL))
{
g_warning ("No alpha function registered for mode %lu.",
mode);
return;
}
if (alpha_data->closure_set)
clutter_alpha_set_closure (alpha, alpha_data->closure);
else
{
clutter_alpha_set_closure_internal (alpha, NULL);
priv->func = alpha_data->func;
priv->user_data = alpha_data->data;
priv->notify = NULL;
}
priv->mode = mode;
}
else
g_assert_not_reached ();
g_object_notify_by_pspec (G_OBJECT (alpha), obj_props[PROP_MODE]);
}

View File

@@ -0,0 +1,138 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Matthew Allum <mallum@openedhand.com>
* Jorn Baayen <jorn@openedhand.com>
* Emmanuele Bassi <ebassi@openedhand.com>
* Tomas Frydrych <tf@openedhand.com>
*
* Copyright (C) 2006, 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/>.
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_ALPHA_H__
#define __CLUTTER_ALPHA_H__
#include <clutter/clutter-timeline.h>
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_ALPHA (clutter_alpha_get_type ())
#define CLUTTER_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ALPHA, ClutterAlpha))
#define CLUTTER_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALPHA, ClutterAlphaClass))
#define CLUTTER_IS_ALPHA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ALPHA))
#define CLUTTER_IS_ALPHA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALPHA))
#define CLUTTER_ALPHA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALPHA, ClutterAlphaClass))
typedef struct _ClutterAlphaClass ClutterAlphaClass;
typedef struct _ClutterAlphaPrivate ClutterAlphaPrivate;
/**
* ClutterAlphaFunc:
* @alpha: a #ClutterAlpha
* @user_data: user data passed to the function
*
* A function returning a value depending on the position of
* the #ClutterTimeline bound to @alpha.
*
* Return value: a floating point value
*
* Since: 0.2
*
* Deprecated: 1.12: Use #ClutterTimelineProgressFunc instead.
*/
typedef gdouble (*ClutterAlphaFunc) (ClutterAlpha *alpha,
gpointer user_data);
/**
* ClutterAlpha:
*
* #ClutterAlpha combines a #ClutterTimeline and a function.
* The contents of the #ClutterAlpha structure are private and should
* only be accessed using the provided API.
*
* Since: 0.2
*
* Deprecated: 1.12: Use #ClutterTimeline instead
*/
struct _ClutterAlpha
{
/*< private >*/
GInitiallyUnowned parent;
ClutterAlphaPrivate *priv;
};
/**
* ClutterAlphaClass:
*
* Base class for #ClutterAlpha
*
* Since: 0.2
*
* Deprecated: 1.12: Use #ClutterTimeline instead
*/
struct _ClutterAlphaClass
{
/*< private >*/
GInitiallyUnownedClass parent_class;
void (*_clutter_alpha_1) (void);
void (*_clutter_alpha_2) (void);
void (*_clutter_alpha_3) (void);
void (*_clutter_alpha_4) (void);
void (*_clutter_alpha_5) (void);
};
CLUTTER_DEPRECATED
GType clutter_alpha_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
ClutterAlpha * clutter_alpha_new (void);
CLUTTER_DEPRECATED
ClutterAlpha * clutter_alpha_new_full (ClutterTimeline *timeline,
gulong mode);
CLUTTER_DEPRECATED
gdouble clutter_alpha_get_alpha (ClutterAlpha *alpha);
CLUTTER_DEPRECATED
void clutter_alpha_set_func (ClutterAlpha *alpha,
ClutterAlphaFunc func,
gpointer data,
GDestroyNotify destroy);
CLUTTER_DEPRECATED
void clutter_alpha_set_closure (ClutterAlpha *alpha,
GClosure *closure);
CLUTTER_DEPRECATED
void clutter_alpha_set_timeline (ClutterAlpha *alpha,
ClutterTimeline *timeline);
CLUTTER_DEPRECATED
ClutterTimeline *clutter_alpha_get_timeline (ClutterAlpha *alpha);
CLUTTER_DEPRECATED
void clutter_alpha_set_mode (ClutterAlpha *alpha,
gulong mode);
CLUTTER_DEPRECATED
gulong clutter_alpha_get_mode (ClutterAlpha *alpha);
G_END_DECLS
#endif /* __CLUTTER_ALPHA_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,152 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Copyright (C) 2008 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Emmanuele Bassi <ebassi@linux.intel.com>
*/
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#ifndef __CLUTTER_ANIMATION_H__
#define __CLUTTER_ANIMATION_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_ANIMATION (clutter_animation_get_type ())
#define CLUTTER_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ANIMATION, ClutterAnimation))
#define CLUTTER_IS_ANIMATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ANIMATION))
#define CLUTTER_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ANIMATION, ClutterAnimationClass))
#define CLUTTER_IS_ANIMATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ANIMATION))
#define CLUTTER_ANIMATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ANIMATION, ClutterAnimationClass))
typedef struct _ClutterAnimationPrivate ClutterAnimationPrivate;
typedef struct _ClutterAnimationClass ClutterAnimationClass;
/**
* ClutterAnimation:
*
* The #ClutterAnimation structure contains only private data and should
* be accessed using the provided functions.
*
* Since: 1.0
*
* Deprecated: 1.12: Use the implicit animation on #ClutterActor
*/
struct _ClutterAnimation
{
/*< private >*/
GObject parent_instance;
ClutterAnimationPrivate *priv;
};
/**
* ClutterAnimationClass:
* @started: class handler for the #ClutterAnimation::started signal
* @completed: class handler for the #ClutterAnimation::completed signal
*
* The #ClutterAnimationClass structure contains only private data and
* should be accessed using the provided functions.
*
* Since: 1.0
*
* Deprecated: 1.12: Use the implicit animation on #ClutterActor
*/
struct _ClutterAnimationClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
void (* started) (ClutterAnimation *animation);
void (* completed) (ClutterAnimation *animation);
/*< private >*/
/* padding for future expansion */
void (*_clutter_reserved1) (void);
void (*_clutter_reserved2) (void);
void (*_clutter_reserved3) (void);
void (*_clutter_reserved4) (void);
void (*_clutter_reserved5) (void);
void (*_clutter_reserved6) (void);
void (*_clutter_reserved7) (void);
void (*_clutter_reserved8) (void);
};
CLUTTER_DEPRECATED
GType clutter_animation_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED_FOR(clutter_property_transition_new)
ClutterAnimation * clutter_animation_new (void);
CLUTTER_DEPRECATED_FOR(clutter_transition_set_animatable)
void clutter_animation_set_object (ClutterAnimation *animation,
GObject *object);
CLUTTER_DEPRECATED_FOR(clutter_timeline_set_progress_mode)
void clutter_animation_set_mode (ClutterAnimation *animation,
gulong mode);
CLUTTER_DEPRECATED_FOR(clutter_timeline_get_progress_mode)
gulong clutter_animation_get_mode (ClutterAnimation *animation);
CLUTTER_DEPRECATED_FOR(clutter_timeline_set_duration)
void clutter_animation_set_duration (ClutterAnimation *animation,
guint msecs);
CLUTTER_DEPRECATED_FOR(clutter_timeline_get_duration)
guint clutter_animation_get_duration (ClutterAnimation *animation);
CLUTTER_DEPRECATED_FOR(clutter_timeline_set_repeat_count)
void clutter_animation_set_loop (ClutterAnimation *animation,
gboolean loop);
CLUTTER_DEPRECATED_FOR(clutter_timeline_get_repeat_count)
gboolean clutter_animation_get_loop (ClutterAnimation *animation);
CLUTTER_DEPRECATED
void clutter_animation_set_timeline (ClutterAnimation *animation,
ClutterTimeline *timeline);
CLUTTER_DEPRECATED
ClutterTimeline * clutter_animation_get_timeline (ClutterAnimation *animation);
CLUTTER_DEPRECATED
gboolean clutter_animation_has_property (ClutterAnimation *animation,
const gchar *property_name);
CLUTTER_DEPRECATED
ClutterInterval * clutter_animation_get_interval (ClutterAnimation *animation,
const gchar *property_name);
/*
* ClutterActor API
*/
CLUTTER_DEPRECATED
ClutterAnimation * clutter_actor_animate (ClutterActor *actor,
gulong mode,
guint duration,
const gchar *first_property_name,
...) G_GNUC_NULL_TERMINATED;
CLUTTER_DEPRECATED
ClutterAnimation * clutter_actor_animate_with_timeline (ClutterActor *actor,
gulong mode,
ClutterTimeline *timeline,
const gchar *first_property_name,
...) G_GNUC_NULL_TERMINATED;
G_END_DECLS
#endif /* __CLUTTER_ANIMATION_DEPRECATED_H__ */

View File

@@ -333,20 +333,21 @@ clutter_group_real_get_preferred_height (ClutterActor *actor,
static void
clutter_group_real_allocate (ClutterActor *actor,
const ClutterActorBox *allocation)
const ClutterActorBox *allocation,
ClutterAllocationFlags flags)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
ClutterActorClass *klass;
klass = CLUTTER_ACTOR_CLASS (clutter_group_parent_class);
klass->allocate (actor, allocation);
klass->allocate (actor, allocation, flags);
if (priv->children == NULL)
return;
clutter_layout_manager_allocate (priv->layout,
CLUTTER_CONTAINER (actor),
allocation);
allocation, flags);
}
static void

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,147 @@
/*
* Clutter.
*
* An OpenGL based 'interactive canvas' library.
*
* Authored By Øyvind Kolås <pippin@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_STATE_H__
#define __CLUTTER_STATE_H__
#include <clutter/clutter-types.h>
G_BEGIN_DECLS
#define CLUTTER_TYPE_STATE_KEY (clutter_state_key_get_type ())
#define CLUTTER_TYPE_STATE (clutter_state_get_type ())
#define CLUTTER_STATE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STATE, ClutterState))
#define CLUTTER_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STATE, ClutterStateClass))
#define CLUTTER_IS_STATE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STATE))
#define CLUTTER_IS_STATE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STATE))
#define CLUTTER_STATE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STATE, ClutterStateClass))
typedef struct _ClutterStatePrivate ClutterStatePrivate;
typedef struct _ClutterStateClass ClutterStateClass;
/**
* ClutterStateKey:
*
* #ClutterStateKey is an opaque structure whose
* members cannot be accessed directly
*
* Since: 1.4
*/
typedef struct _ClutterStateKey ClutterStateKey;
/**
* ClutterState:
*
* The #ClutterState structure contains only
* private data and should be accessed using the provided API
*
* Since: 1.4
*/
struct _ClutterState
{
/*< private >*/
GObject parent;
ClutterStatePrivate *priv;
};
/**
* ClutterStateClass:
* @completed: class handler for the #ClutterState::completed signal
*
* The #ClutterStateClass structure contains
* only private data
*
* Since: 1.4
*
* Deprecated: 1.12
*/
struct _ClutterStateClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
void (* completed) (ClutterState *state);
/*< private >*/
/* padding for future expansion */
gpointer _padding_dummy[8];
};
CLUTTER_DEPRECATED
GType clutter_state_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
ClutterState *clutter_state_new (void);
CLUTTER_DEPRECATED
ClutterTimeline * clutter_state_set_state (ClutterState *state,
const gchar *target_state_name);
CLUTTER_DEPRECATED
ClutterTimeline * clutter_state_warp_to_state (ClutterState *state,
const gchar *target_state_name);
CLUTTER_DEPRECATED
ClutterState * clutter_state_set_key (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name,
GObject *object,
const gchar *property_name,
guint mode,
const GValue *value,
gdouble pre_delay,
gdouble post_delay);
CLUTTER_DEPRECATED
void clutter_state_set_duration (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name,
guint duration);
CLUTTER_DEPRECATED
guint clutter_state_get_duration (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name);
CLUTTER_DEPRECATED
void clutter_state_set (ClutterState *state,
const gchar *source_state_name,
const gchar *target_state_name,
gpointer first_object,
const gchar *first_property_name,
gulong first_mode,
...) G_GNUC_NULL_TERMINATED;
CLUTTER_DEPRECATED
GList * clutter_state_get_states (ClutterState *state);
CLUTTER_DEPRECATED
const gchar * clutter_state_get_state (ClutterState *state);
/*
* ClutterStateKey
*/
CLUTTER_DEPRECATED
GType clutter_state_key_get_type (void) G_GNUC_CONST;
CLUTTER_DEPRECATED
GType clutter_state_key_get_property_type (const ClutterStateKey *key);
G_END_DECLS
#endif /* __CLUTTER_STATE_H__ */

View File

@@ -114,7 +114,6 @@ clutter_sources = [
'clutter-constraint.c',
'clutter-container.c',
'clutter-content.c',
'clutter-damage-history.c',
'clutter-deform-effect.c',
'clutter-desaturate-effect.c',
'clutter-effect.c',
@@ -186,7 +185,6 @@ clutter_private_headers = [
'clutter-bezier.h',
'clutter-constraint-private.h',
'clutter-content-private.h',
'clutter-damage-history.h',
'clutter-debug.h',
'clutter-easing.h',
'clutter-effect-private.h',
@@ -221,18 +219,24 @@ clutter_nonintrospected_sources = [
clutter_deprecated_headers = [
'deprecated/clutter-actor.h',
'deprecated/clutter-alpha.h',
'deprecated/clutter-animation.h',
'deprecated/clutter-box.h',
'deprecated/clutter-container.h',
'deprecated/clutter-group.h',
'deprecated/clutter-rectangle.h',
'deprecated/clutter-stage.h',
'deprecated/clutter-state.h',
'deprecated/clutter-timeline.h',
]
clutter_deprecated_sources = [
'deprecated/clutter-alpha.c',
'deprecated/clutter-animation.c',
'deprecated/clutter-box.c',
'deprecated/clutter-group.c',
'deprecated/clutter-rectangle.c',
'deprecated/clutter-state.c',
]
clutter_backend_sources = []
@@ -333,20 +337,35 @@ clutter_build_config_h = configure_file(
)
clutter_built_private_headers += clutter_build_config_h
cdata = configuration_data()
clutter_config_defines = []
if have_wayland
cdata.set10('CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT', true)
clutter_config_defines += [
'#define CLUTTER_HAS_WAYLAND_COMPOSITOR_SUPPORT 1',
]
endif
if have_x11
cdata.set_quoted('CLUTTER_WINDOWING_X11', 'x11')
cdata.set_quoted('CLUTTER_INPUT_X11', 'x11')
cdata.set_quoted('CLUTTER_WINDOWING_GLX', 'glx')
clutter_config_defines += [
'#define CLUTTER_WINDOWING_X11 "x11"',
'#define CLUTTER_INPUT_X11 "x11"',
'#define CLUTTER_WINDOWING_GLX "glx"',
]
endif
if have_native_backend
cdata.set_quoted('CLUTTER_WINDOWING_EGL', 'eglnative')
cdata.set_quoted('CLUTTER_INPUT_EVDEV', 'evdev')
clutter_config_defines += [
'#define CLUTTER_WINDOWING_EGL "eglnative"',
'#define CLUTTER_INPUT_EVDEV "evdev"',
]
endif
cdata.set_quoted('CLUTTER_INPUT_NULL', 'null')
clutter_config_defines += [
'#define CLUTTER_INPUT_NULL "null"',
]
clutter_config_defines_string = ''
foreach clutter_config_define : clutter_config_defines
clutter_config_defines_string += clutter_config_define + '\n'
endforeach
cdata = configuration_data()
cdata.set('CLUTTER_CONFIG_DEFINES', clutter_config_defines_string)
clutter_config_h = configure_file(
input: 'clutter-config.h.in',

View File

@@ -158,7 +158,7 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data)
supported. */
if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) !=
(_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) ||
!cogl_has_feature (ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER))
!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER))
return FALSE;
dst_offscreen = _cogl_offscreen_new_with_texture_full

View File

@@ -193,8 +193,6 @@ cogl_is_context (void *object);
* expected to return age values other than 0.
* @COGL_FEATURE_ID_PRESENTATION_TIME: Whether frame presentation
* time stamps will be recorded in #CoglFrameInfo objects.
* @COGL_FEATURE_ID_BLIT_FRAMEBUFFER: Whether blitting using
* cogl_blit_framebuffer() is supported.
*
* All the capabilities that can vary between different GPUs supported
* by Cogl. Applications that depend on any of these features should explicitly
@@ -213,7 +211,6 @@ typedef enum _CoglFeatureID
COGL_FEATURE_ID_TEXTURE_RG,
COGL_FEATURE_ID_BUFFER_AGE,
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
COGL_FEATURE_ID_BLIT_FRAMEBUFFER,
/*< private >*/
_COGL_N_FEATURE_IDS /*< skip >*/

View File

@@ -34,22 +34,12 @@
#include "cogl-dma-buf-handle.h"
#include "cogl-object.h"
#include <errno.h>
#include <gio/gio.h>
#include <linux/dma-buf.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
struct _CoglDmaBufHandle
{
CoglFramebuffer *framebuffer;
int dmabuf_fd;
int width;
int height;
int stride;
int offset;
int bpp;
gpointer user_data;
GDestroyNotify destroy_func;
};
@@ -57,11 +47,6 @@ struct _CoglDmaBufHandle
CoglDmaBufHandle *
cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
int dmabuf_fd,
int width,
int height,
int stride,
int offset,
int bpp,
gpointer user_data,
GDestroyNotify destroy_func)
{
@@ -76,12 +61,6 @@ cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
dmabuf_handle->user_data = user_data;
dmabuf_handle->destroy_func = destroy_func;
dmabuf_handle->width = width;
dmabuf_handle->height = height;
dmabuf_handle->stride = stride;
dmabuf_handle->offset = offset;
dmabuf_handle->bpp = bpp;
return dmabuf_handle;
}
@@ -101,93 +80,6 @@ cogl_dma_buf_handle_free (CoglDmaBufHandle *dmabuf_handle)
g_free (dmabuf_handle);
}
static gboolean
sync_read (CoglDmaBufHandle *dmabuf_handle,
uint64_t start_or_end,
GError **error)
{
struct dma_buf_sync sync = { 0 };
sync.flags = start_or_end | DMA_BUF_SYNC_READ;
while (TRUE)
{
int ret;
ret = ioctl (dmabuf_handle->dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync);
if (ret == -1 && errno == EINTR)
{
continue;
}
else if (ret == -1)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"ioctl: %s", g_strerror (errno));
return FALSE;
}
else
{
break;
}
}
return TRUE;
}
gboolean
cogl_dma_buf_handle_sync_read_start (CoglDmaBufHandle *dmabuf_handle,
GError **error)
{
return sync_read (dmabuf_handle, DMA_BUF_SYNC_START, error);
}
gboolean
cogl_dma_buf_handle_sync_read_end (CoglDmaBufHandle *dmabuf_handle,
GError **error)
{
return sync_read (dmabuf_handle, DMA_BUF_SYNC_END, error);
}
gpointer
cogl_dma_buf_handle_mmap (CoglDmaBufHandle *dmabuf_handle,
GError **error)
{
size_t size;
gpointer data;
size = dmabuf_handle->height * dmabuf_handle->stride;
data = mmap (NULL, size, PROT_READ, MAP_PRIVATE,
dmabuf_handle->dmabuf_fd,
dmabuf_handle->offset);
if (data == MAP_FAILED)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"mmap failed: %s", g_strerror (errno));
return NULL;
}
return data;
}
gboolean
cogl_dma_buf_handle_munmap (CoglDmaBufHandle *dmabuf_handle,
gpointer data,
GError **error)
{
size_t size;
size = dmabuf_handle->height * dmabuf_handle->stride;
if (munmap (data, size) != 0)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
"munmap failed: %s", g_strerror (errno));
return FALSE;
}
return TRUE;
}
CoglFramebuffer *
cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle)
{
@@ -200,32 +92,3 @@ cogl_dma_buf_handle_get_fd (CoglDmaBufHandle *dmabuf_handle)
return dmabuf_handle->dmabuf_fd;
}
int
cogl_dma_buf_handle_get_width (CoglDmaBufHandle *dmabuf_handle)
{
return dmabuf_handle->width;
}
int
cogl_dma_buf_handle_get_height (CoglDmaBufHandle *dmabuf_handle)
{
return dmabuf_handle->height;
}
int
cogl_dma_buf_handle_get_stride (CoglDmaBufHandle *dmabuf_handle)
{
return dmabuf_handle->stride;
}
int
cogl_dma_buf_handle_get_offset (CoglDmaBufHandle *dmabuf_handle)
{
return dmabuf_handle->offset;
}
int
cogl_dma_buf_handle_get_bpp (CoglDmaBufHandle *dmabuf_handle)
{
return dmabuf_handle->bpp;
}

View File

@@ -46,12 +46,7 @@
COGL_EXPORT CoglDmaBufHandle *
cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
int dmabuf_fd,
int width,
int height,
int stride,
int offset,
int bpp,
gpointer user_data,
gpointer data,
GDestroyNotify destroy_func);
/**
@@ -63,23 +58,6 @@ cogl_dma_buf_handle_new (CoglFramebuffer *framebuffer,
COGL_EXPORT void
cogl_dma_buf_handle_free (CoglDmaBufHandle *dmabuf_handle);
COGL_EXPORT gboolean
cogl_dma_buf_handle_sync_read_start (CoglDmaBufHandle *dmabuf_handle,
GError **error);
COGL_EXPORT gboolean
cogl_dma_buf_handle_sync_read_end (CoglDmaBufHandle *dmabuf_handle,
GError **error);
COGL_EXPORT gpointer
cogl_dma_buf_handle_mmap (CoglDmaBufHandle *dmabuf_handle,
GError **error);
COGL_EXPORT gboolean
cogl_dma_buf_handle_munmap (CoglDmaBufHandle *dmabuf_handle,
gpointer data,
GError **error);
/**
* cogl_dma_buf_handle_get_framebuffer: (skip)
*
@@ -101,44 +79,5 @@ cogl_dma_buf_handle_get_framebuffer (CoglDmaBufHandle *dmabuf_handle);
COGL_EXPORT int
cogl_dma_buf_handle_get_fd (CoglDmaBufHandle *dmabuf_handle);
/**
* cogl_dmabuf_handle_get_width: (skip)
*
* Returns: the buffer width
*/
COGL_EXPORT int
cogl_dma_buf_handle_get_width (CoglDmaBufHandle *dmabuf_handle);
/**
* cogl_dmabuf_handle_get_height: (skip)
*
* Returns: the buffer height
*/
COGL_EXPORT int
cogl_dma_buf_handle_get_height (CoglDmaBufHandle *dmabuf_handle);
/**
* cogl_dmabuf_handle_get_stride: (skip)
*
* Returns: the buffer stride
*/
COGL_EXPORT int
cogl_dma_buf_handle_get_stride (CoglDmaBufHandle *dmabuf_handle);
/**
* cogl_dmabuf_handle_get_offset: (skip)
*
* Returns: the buffer offset
*/
COGL_EXPORT int
cogl_dma_buf_handle_get_offset (CoglDmaBufHandle *dmabuf_handle);
/**
* cogl_dmabuf_handle_get_bpp: (skip)
*
* Returns: the number of bytes per pixel
*/
COGL_EXPORT int
cogl_dma_buf_handle_get_bpp (CoglDmaBufHandle *dmabuf_handle);
#endif /* __COGL_DMA_BUF_HANDLE_H__ */

View File

@@ -1292,7 +1292,7 @@ cogl_blit_framebuffer (CoglFramebuffer *src,
int src_x1, src_y1, src_x2, src_y2;
int dst_x1, dst_y1, dst_x2, dst_y2;
if (!cogl_has_feature (ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER))
if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER))
{
g_set_error_literal (error, COGL_SYSTEM_ERROR,
COGL_SYSTEM_ERROR_UNSUPPORTED,

View File

@@ -1509,7 +1509,7 @@ cogl_is_framebuffer (void *object);
*
* This blits a region of the color buffer of the source buffer
* to the destination buffer. This function should only be
* called if the COGL_FEATURE_ID_BLIT_FRAMEBUFFER feature is
* called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is
* advertised.
*
* The source and destination rectangles are defined in offscreen

View File

@@ -405,27 +405,6 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
return winsys->onscreen_get_buffer_age (onscreen);
}
void
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys;
CoglFrameInfo *info;
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT));
info = _cogl_frame_info_new ();
info->frame_counter = onscreen->frame_counter;
g_queue_push_tail (&onscreen->pending_frame_infos, info);
winsys = _cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_direct_scanout (onscreen, scanout);
onscreen->frame_counter++;
}
#ifdef COGL_HAS_X11_SUPPORT
uint32_t
cogl_x11_onscreen_get_window_xid (CoglOnscreen *onscreen)

View File

@@ -50,8 +50,6 @@ G_BEGIN_DECLS
typedef struct _CoglOnscreen CoglOnscreen;
#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
typedef struct _CoglScanout CoglScanout;
/**
* cogl_onscreen_get_gtype:
*
@@ -286,13 +284,6 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
int n_rectangles);
/**
* cogl_onscreen_direct_scanout: (skip)
*/
COGL_EXPORT void
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout);
/**
* cogl_onscreen_swap_region:
* @onscreen: A #CoglOnscreen framebuffer

View File

@@ -1361,17 +1361,6 @@ cogl_pipeline_set_layer_filters (CoglPipeline *pipeline,
sampler_state);
}
void
cogl_pipeline_set_layer_max_mipmap_level (CoglPipeline *pipeline,
int layer,
int max_level)
{
CoglTexture *texture = cogl_pipeline_get_layer_texture (pipeline, layer);
if (texture != NULL)
cogl_texture_set_max_level (texture, max_level);
}
const CoglSamplerCacheEntry *
_cogl_pipeline_layer_get_sampler_state (CoglPipelineLayer *layer)
{

View File

@@ -568,11 +568,6 @@ cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline,
int layer,
CoglSnippet *snippet);
COGL_EXPORT void
cogl_pipeline_set_layer_max_mipmap_level (CoglPipeline *pipeline,
int layer,
int max_level);
G_END_DECLS
#endif /* __COGL_PIPELINE_LAYER_STATE_H__ */

View File

@@ -42,6 +42,7 @@ typedef enum
{
COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE,
COGL_PRIVATE_FEATURE_MESA_PACK_INVERT,
COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER,
COGL_PRIVATE_FEATURE_PBOS,
COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL,
COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL,

View File

@@ -1,27 +0,0 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "cogl-config.h"
#include "cogl-scanout.h"
G_DEFINE_INTERFACE (CoglScanout, cogl_scanout, G_TYPE_OBJECT)
static void
cogl_scanout_default_init (CoglScanoutInterface *iface)
{
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef COGL_SCANOUT_H
#define COGL_SCANOUT_H
#include "cogl/cogl-types.h"
#include <glib-object.h>
#define COGL_TYPE_SCANOUT (cogl_scanout_get_type ())
COGL_EXPORT
G_DECLARE_INTERFACE (CoglScanout, cogl_scanout,
COGL, SCANOUT, GObject)
struct _CoglScanoutInterface
{
GTypeInterface parent_iface;
};
#endif /* COGL_SCANOUT_H */

View File

@@ -204,8 +204,7 @@ struct _CoglTexture
CoglContext *context;
CoglTextureLoader *loader;
GList *framebuffers;
int max_level_set;
int max_level_requested;
int max_level;
int width;
int height;
gboolean allocated;
@@ -378,10 +377,6 @@ _cogl_texture_needs_premult_conversion (CoglPixelFormat src_format,
int
_cogl_texture_get_n_levels (CoglTexture *texture);
void
cogl_texture_set_max_level (CoglTexture *texture,
int max_level);
void
_cogl_texture_get_level_size (CoglTexture *texture,
int level,

View File

@@ -115,8 +115,7 @@ _cogl_texture_init (CoglTexture *texture,
const CoglTextureVtable *vtable)
{
texture->context = context;
texture->max_level_set = 0;
texture->max_level_requested = 1000; /* OpenGL default GL_TEXTURE_MAX_LEVEL */
texture->max_level = 0;
texture->width = width;
texture->height = height;
texture->allocated = FALSE;
@@ -230,16 +229,8 @@ _cogl_texture_get_n_levels (CoglTexture *texture)
int width = cogl_texture_get_width (texture);
int height = cogl_texture_get_height (texture);
int max_dimension = MAX (width, height);
int n_levels = _cogl_util_fls (max_dimension);
return MIN (n_levels, texture->max_level_requested + 1);
}
void
cogl_texture_set_max_level (CoglTexture *texture,
int max_level)
{
texture->max_level_requested = max_level;
return _cogl_util_fls (max_dimension);
}
void

View File

@@ -122,7 +122,6 @@
#include <cogl/cogl-fence.h>
#include <cogl/cogl-glib-source.h>
#include <cogl/cogl-trace.h>
#include <cogl/cogl-scanout.h>
/* XXX: This will definitly go away once all the Clutter winsys
* code has been migrated down into Cogl! */
#include <cogl/deprecated/cogl-clutter.h>

View File

@@ -388,8 +388,8 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
{
/* NB: Currently we only take advantage of binding separate
* read/write buffers for framebuffer blit purposes. */
g_return_if_fail (cogl_has_feature
(ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER));
g_return_if_fail (_cogl_has_private_feature
(ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER));
_cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
_cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);

View File

@@ -567,9 +567,6 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
&gl_format,
&gl_type);
if (tex->max_level_set < level)
cogl_texture_gl_set_max_level (tex, level);
status = ctx->texture_driver->upload_subregion_to_gl (ctx,
tex,
src_x, src_y,
@@ -583,6 +580,8 @@ _cogl_texture_2d_gl_copy_from_bitmap (CoglTexture2D *tex_2d,
cogl_object_unref (upload_bmp);
_cogl_texture_gl_maybe_update_max_level (tex, level);
return status;
}

View File

@@ -53,8 +53,8 @@ _cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture,
unsigned int mag_filter);
void
cogl_texture_gl_set_max_level (CoglTexture *texture,
int max_level);
_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture,
int max_level);
void
_cogl_texture_gl_generate_mipmaps (CoglTexture *texture);

View File

@@ -97,36 +97,32 @@ _cogl_texture_gl_flush_legacy_texobj_filters (CoglTexture *texture,
min_filter, mag_filter);
}
/* GL and GLES3 have this by default, but GLES2 does not except via extension.
* So really it's probably always available. Even if we used it and it wasn't
* available in some driver then there are no adverse consequences to the
* command simply being ignored...
*/
#ifndef GL_TEXTURE_MAX_LEVEL
#define GL_TEXTURE_MAX_LEVEL 0x813D
#endif
void
cogl_texture_gl_set_max_level (CoglTexture *texture,
int max_level)
_cogl_texture_gl_maybe_update_max_level (CoglTexture *texture,
int max_level)
{
/* This isn't supported on GLES */
#ifdef HAVE_COGL_GL
CoglContext *ctx = texture->context;
if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL))
if (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_MAX_LEVEL) &&
texture->max_level < max_level)
{
CoglContext *ctx = texture->context;
GLuint gl_handle;
GLenum gl_target;
cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);
texture->max_level_set = max_level;
texture->max_level = max_level;
_cogl_bind_gl_texture_transient (gl_target,
gl_handle);
GE( ctx, glTexParameteri (gl_target,
GL_TEXTURE_MAX_LEVEL, texture->max_level_set));
GL_TEXTURE_MAX_LEVEL, texture->max_level));
}
#endif /* HAVE_COGL_GL */
}
void
@@ -137,8 +133,7 @@ _cogl_texture_gl_generate_mipmaps (CoglTexture *texture)
GLuint gl_handle;
GLenum gl_target;
if (texture->max_level_set != n_levels - 1)
cogl_texture_gl_set_max_level (texture, n_levels - 1);
_cogl_texture_gl_maybe_update_max_level (texture, n_levels - 1);
cogl_texture_get_gl_texture (texture, &gl_handle, &gl_target);

View File

@@ -455,8 +455,8 @@ _cogl_driver_update_features (CoglContext *ctx,
TRUE);
if (ctx->glBlitFramebuffer)
COGL_FLAGS_SET (ctx->features,
COGL_FEATURE_ID_BLIT_FRAMEBUFFER, TRUE);
COGL_FLAGS_SET (private_features,
COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE);
COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_PBOS, TRUE);

View File

@@ -255,7 +255,7 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
* glTexImage2D first to assert that the storage for this
* level exists.
*/
if (texture->max_level_set < level)
if (texture->max_level < level)
{
ctx->glTexImage2D (gl_target,
level,

View File

@@ -318,8 +318,8 @@ _cogl_driver_update_features (CoglContext *context,
COGL_FLAGS_SET (private_features, COGL_PRIVATE_FEATURE_SAMPLER_OBJECTS, TRUE);
if (context->glBlitFramebuffer)
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_BLIT_FRAMEBUFFER, TRUE);
COGL_FLAGS_SET (private_features,
COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE);
if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions))
{

View File

@@ -303,7 +303,7 @@ _cogl_texture_driver_upload_subregion_to_gl (CoglContext *ctx,
* glTexImage2D first to assert that the storage for this
* level exists.
*/
if (texture->max_level_set < level)
if (texture->max_level < level)
{
ctx->glTexImage2D (gl_target,
level,

View File

@@ -122,7 +122,6 @@ cogl_nonintrospected_headers = [
'cogl-version.h',
'cogl-gtype-private.h',
'cogl-glib-source.h',
'cogl-scanout.h',
]
cogl_nodist_headers = [
@@ -348,7 +347,6 @@ cogl_sources = [
'cogl-closure-list.c',
'cogl-fence.c',
'cogl-fence-private.h',
'cogl-scanout.c',
'deprecated/cogl-material-compat.c',
'deprecated/cogl-program.c',
'deprecated/cogl-program-private.h',

View File

@@ -33,7 +33,6 @@
#include "cogl-renderer.h"
#include "cogl-onscreen.h"
#include "cogl-scanout.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include "cogl-texture-pixmap-x11-private.h"
@@ -118,10 +117,6 @@ typedef struct _CoglWinsysVtable
const int *rectangles,
int n_rectangles);
void
(*onscreen_direct_scanout) (CoglOnscreen *onscreen,
CoglScanout *scanout);
void
(*onscreen_set_visibility) (CoglOnscreen *onscreen,
gboolean visibility);

View File

@@ -17,7 +17,6 @@ cogl_config_h = configure_file(
cogl_pkg_deps = [
glib_dep,
gio_dep,
gobject_dep,
graphene_dep,
]

View File

@@ -1,7 +1,5 @@
#!/usr/bin/env bash
set -o pipefail
if test -z "$G_DEBUG"; then
G_DEBUG=fatal-warnings
else
@@ -71,12 +69,7 @@ get_status()
run_test()
{
if [ -n "${VERBOSE-}" ]; then
echo "running $TEST_BINARY $1:"
$TEST_BINARY $1 2>&1 | tee "$LOG"
else
$($TEST_BINARY $1 &> "$LOG")
fi
$("$TEST_BINARY" "$1" &> "$LOG")
TMP=$?
var_name=$2_result
eval "$var_name=$TMP"

View File

@@ -70,12 +70,3 @@
/* Whether Xwayland has -initfd option */
#mesondefine HAVE_XWAYLAND_INITFD
/* Whether the mkostemp function exists */
#mesondefine HAVE_MKOSTEMP
/* Whether the posix_fallocate function exists */
#mesondefine HAVE_POSIX_FALLOCATE
/* Whether the memfd_create function exists */
#mesondefine HAVE_MEMFD_CREATE

View File

@@ -1,5 +1,5 @@
project('mutter', 'c',
version: '3.37.1',
version: '3.37.0',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)
@@ -408,20 +408,6 @@ if have_wayland
endif
endif
optional_functions = [
'mkostemp',
'posix_fallocate',
'memfd_create',
]
foreach function : optional_functions
if cc.has_function(function)
cdata.set('HAVE_' + function.to_upper(), 1)
else
message('Optional function ' + function + ' missing')
endif
endforeach
xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules')
cdata.set_quoted('XWAYLAND_GRAB_DEFAULT_ACCESS_RULES',
xwayland_grab_default_access_rules)
@@ -487,7 +473,6 @@ output = [
' Cogl tests............... ' + have_cogl_tests.to_string(),
' Clutter tests............ ' + have_clutter_tests.to_string(),
' Installed tests.......... ' + have_installed_tests.to_string(),
' Coverage................. ' + get_option('b_coverage').to_string(),
'',
' Now type \'ninja -C ' + meson.build_root() + '\' to build ' + meson.project_name(),
'',

View File

@@ -13,8 +13,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2020-03-30 20:11+0000\n"
"PO-Revision-Date: 2020-04-06 23:13+0200\n"
"POT-Creation-Date: 2019-08-06 00:49+0000\n"
"PO-Revision-Date: 2019-09-05 23:42+0200\n"
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
@@ -22,7 +22,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
"X-Generator: Poedit 2.2.1\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@@ -435,33 +435,20 @@ msgstr "Zusatztaste zum Finden des Zeigers"
msgid "This key will initiate the “locate pointer” action."
msgstr "Diese Taste wird die Aktion »Zeiger finden« auslösen."
#: data/org.gnome.mutter.gschema.xml.in:142
msgid "Timeout for check-alive ping"
msgstr "Reaktionsschwellwert bei Kontaktkontrolle"
#: data/org.gnome.mutter.gschema.xml.in:143
msgid ""
"Number of milliseconds a client has to respond to a ping request in order to "
"not be detected as frozen. Using 0 will disable the alive check completely."
msgstr ""
"Zeit in Millisekunden, innerhalb welcher ein Client auf eine "
"Kontaktkontrolle antworten muss, um nicht als abgestürzt zu gelten. »0« "
"bedeutet, dass die Kontaktkontrolle ausgeschaltet wird."
#: data/org.gnome.mutter.gschema.xml.in:165
#: data/org.gnome.mutter.gschema.xml.in:155
msgid "Select window from tab popup"
msgstr "Fenster aus Tab-Anzeige auswählen"
#: data/org.gnome.mutter.gschema.xml.in:170
#: data/org.gnome.mutter.gschema.xml.in:160
msgid "Cancel tab popup"
msgstr "Tab-Anzeige abbrechen"
#: data/org.gnome.mutter.gschema.xml.in:175
#: data/org.gnome.mutter.gschema.xml.in:165
msgid "Switch monitor configurations"
msgstr "Bildschirmkonfigurationen wechseln"
# Ich denke nicht, dass »rotate« hier die Bildschirmdrehung meint, sondern eher eine Liste aus Konfigurationen rotiert (d.h. umgewälzt) wird.
#: data/org.gnome.mutter.gschema.xml.in:180
#: data/org.gnome.mutter.gschema.xml.in:170
msgid "Rotates the built-in monitor configuration"
msgstr "Wechselt die Konfiguration des eingebauten Bildschirms"
@@ -582,7 +569,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2631
#: src/backends/meta-input-settings.c:2531
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Moduswechsel (Gruppe %d)"
@@ -590,34 +577,34 @@ msgstr "Moduswechsel (Gruppe %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2654
#: src/backends/meta-input-settings.c:2554
msgid "Switch monitor"
msgstr "Bildschirm wechseln"
#: src/backends/meta-input-settings.c:2656
#: src/backends/meta-input-settings.c:2556
msgid "Show on-screen help"
msgstr "Bildschirmhilfe anzeigen"
#: src/backends/meta-monitor.c:226
#: src/backends/meta-monitor.c:223
msgid "Built-in display"
msgstr "Eingebaute Anzeige"
#: src/backends/meta-monitor.c:255
#: src/backends/meta-monitor.c:252
msgid "Unknown"
msgstr "Unbekannt"
#: src/backends/meta-monitor.c:257
#: src/backends/meta-monitor.c:254
msgid "Unknown Display"
msgstr "Unbekannte Anzeige"
#: src/backends/meta-monitor.c:265
#: src/backends/meta-monitor.c:262
#, c-format
msgctxt ""
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
msgid "%s %s"
msgstr "%s %s"
#: src/backends/meta-monitor.c:273
#: src/backends/meta-monitor.c:270
#, c-format
msgctxt ""
"This is a monitor vendor name followed by product/model name where size in "
@@ -627,13 +614,13 @@ msgstr "%s %s"
# https://de.wikipedia.org/wiki/Composition-Manager
#. Translators: this string will appear in Sysprof
#: src/backends/meta-profiler.c:79
#: src/backends/meta-profiler.c:82
msgid "Compositor"
msgstr "Compositor"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:533
#: src/compositor/compositor.c:510
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@@ -645,47 +632,47 @@ msgstr ""
msgid "Bell event"
msgstr "Klangereignis"
#: src/core/main.c:190
#: src/core/main.c:185
msgid "Disable connection to session manager"
msgstr "Verbindung zur Sitzungsverwaltung deaktivieren"
#: src/core/main.c:196
#: src/core/main.c:191
msgid "Replace the running window manager"
msgstr "Den aktuellen Fensterverwalter ersetzen"
#: src/core/main.c:202
#: src/core/main.c:197
msgid "Specify session management ID"
msgstr "Kennung der Sitzungsverwaltung angeben"
#: src/core/main.c:207
#: src/core/main.c:202
msgid "X Display to use"
msgstr "Zu verwendende X-Anzeige"
#: src/core/main.c:213
#: src/core/main.c:208
msgid "Initialize session from savefile"
msgstr "Sitzung anhand gespeicherter Datei starten"
#: src/core/main.c:219
#: src/core/main.c:214
msgid "Make X calls synchronous"
msgstr "X-Aufrufe abgleichen"
#: src/core/main.c:226
#: src/core/main.c:221
msgid "Run as a wayland compositor"
msgstr "Als Wayland-Compositor ausführen"
#: src/core/main.c:232
#: src/core/main.c:227
msgid "Run as a nested compositor"
msgstr "Als eingebetteten Compositor ausführen"
#: src/core/main.c:238
#: src/core/main.c:233
msgid "Run wayland compositor without starting Xwayland"
msgstr "Wayland-Compositor ausführen, ohne Xwayland zu starten"
#: src/core/main.c:246
#: src/core/main.c:241
msgid "Run as a full display server, rather than nested"
msgstr "Als vollwertigen Display-Server verwenden (nicht eingebettet)"
#: src/core/main.c:252
#: src/core/main.c:247
msgid "Run with X11 backend"
msgstr "Mit X11-Backend ausführen"
@@ -741,21 +728,21 @@ msgstr "Version ausgeben"
msgid "Mutter plugin to use"
msgstr "Zu benutzendes Mutter-Plugin"
#: src/core/prefs.c:1911
#: src/core/prefs.c:1849
#, c-format
msgid "Workspace %d"
msgstr "Arbeitsfläche %d"
#: src/core/util.c:122
#: src/core/util.c:121
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter wurde ohne Unterstützung für den redseligen Modus kompiliert\n"
#: src/wayland/meta-wayland-tablet-pad.c:568
#: src/wayland/meta-wayland-tablet-pad.c:567
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Moduswechsel: Modus %d"
#: src/x11/meta-x11-display.c:676
#: src/x11/meta-x11-display.c:671
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@@ -764,21 +751,21 @@ msgstr ""
"Bildschirm »%s« hat bereits einen Fensterverwalter. Versuchen Sie die Option "
"»--replace«, um den aktuellen Fensterverwalter zu ersetzen."
#: src/x11/meta-x11-display.c:1089
#: src/x11/meta-x11-display.c:1032
msgid "Failed to initialize GDK\n"
msgstr "GDK konnte nicht initialisiert werden\n"
#: src/x11/meta-x11-display.c:1113
#: src/x11/meta-x11-display.c:1056
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n"
#: src/x11/meta-x11-display.c:1196
#: src/x11/meta-x11-display.c:1140
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Bildschirm %d auf Anzeige »%s« ist ungültig\n"
#: src/x11/meta-x11-selection-input-stream.c:460
#: src/x11/meta-x11-selection-input-stream.c:445
#, c-format
msgid "Format %s not supported"
msgstr "Format %s wird nicht unterstützt"

View File

@@ -108,14 +108,6 @@ struct _MetaBackendClass
void meta_init_backend (GType backend_gtype);
#ifdef HAVE_WAYLAND
MetaWaylandCompositor * meta_backend_get_wayland_compositor (MetaBackend *backend);
void meta_backend_init_wayland_display (MetaBackend *backend);
void meta_backend_init_wayland (MetaBackend *backend);
#endif
ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend);
MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,

View File

@@ -49,11 +49,8 @@ typedef struct _MetaTileInfo MetaTileInfo;
typedef struct _MetaRenderer MetaRenderer;
typedef struct _MetaRendererView MetaRendererView;
typedef struct _MetaRemoteDesktop MetaRemoteDesktop;
typedef struct _MetaScreenCast MetaScreenCast;
typedef struct _MetaScreenCastSession MetaScreenCastSession;
typedef struct _MetaScreenCastStream MetaScreenCastStream;
typedef struct _MetaWaylandCompositor MetaWaylandCompositor;
#endif /* META_BACKEND_TYPE_H */

View File

@@ -81,10 +81,6 @@
#include "backends/native/meta-backend-native.h"
#endif
#ifdef HAVE_WAYLAND
#include "wayland/meta-wayland.h"
#endif
enum
{
KEYMAP_CHANGED,
@@ -134,10 +130,6 @@ struct _MetaBackendPrivate
MetaRemoteDesktop *remote_desktop;
#endif
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *wayland_compositor;
#endif
#ifdef HAVE_PROFILER
MetaProfiler *profiler;
#endif
@@ -560,12 +552,12 @@ meta_backend_real_post_init (MetaBackend *backend)
}
#ifdef HAVE_REMOTE_DESKTOP
priv->remote_access_controller =
g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER, NULL);
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
priv->screen_cast = meta_screen_cast_new (backend,
priv->dbus_session_watcher);
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
priv->remote_access_controller =
meta_remote_access_controller_new (priv->remote_desktop, priv->screen_cast);
#endif /* HAVE_REMOTE_DESKTOP */
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
@@ -817,6 +809,9 @@ static MetaMonitorManager *
meta_backend_create_monitor_manager (MetaBackend *backend,
GError **error)
{
if (g_getenv ("META_DUMMY_MONITORS"))
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend,
error);
}
@@ -872,120 +867,6 @@ system_bus_gotten_cb (GObject *object,
NULL);
}
#ifdef HAVE_WAYLAND
MetaWaylandCompositor *
meta_backend_get_wayland_compositor (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
return priv->wayland_compositor;
}
void
meta_backend_init_wayland_display (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
priv->wayland_compositor = meta_wayland_compositor_new (backend);
}
void
meta_backend_init_wayland (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
meta_wayland_compositor_setup (priv->wayland_compositor);
}
#endif
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
* the X fd, but we do have to deal with dispatching events that accumulate
* in the clutter queue. This happens, for example, when clutter generate
* enter/leave events on mouse motion - several events are queued in the
* clutter queue but only one dispatched. It could also happen because of
* explicit calls to clutter_event_put(). We add a very simple custom
* event loop source which is simply responsible for pulling events off
* of the queue and dispatching them before we block for new events.
*/
static gboolean
clutter_source_prepare (GSource *source,
int *timeout)
{
*timeout = -1;
return clutter_events_pending ();
}
static gboolean
clutter_source_check (GSource *source)
{
return clutter_events_pending ();
}
static gboolean
clutter_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterEvent *event = clutter_event_get ();
if (event)
{
clutter_do_event (event);
clutter_event_free (event);
}
return TRUE;
}
static GSourceFuncs clutter_source_funcs = {
clutter_source_prepare,
clutter_source_check,
clutter_source_dispatch
};
static ClutterBackend *
meta_get_clutter_backend (void)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_get_clutter_backend (backend);
}
static gboolean
init_clutter (MetaBackend *backend,
GError **error)
{
GSource *source;
clutter_set_custom_backend_func (meta_get_clutter_backend);
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unable to initialize Clutter");
return FALSE;
}
source = g_source_new (&clutter_source_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);
return TRUE;
}
static void
meta_backend_post_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
META_BACKEND_GET_CLASS (backend)->post_init (backend);
meta_settings_post_init (priv->settings);
}
static gboolean
meta_backend_initable_init (GInitable *initable,
GCancellable *cancellable,
@@ -1024,11 +905,6 @@ meta_backend_initable_init (GInitable *initable,
priv->profiler = meta_profiler_new ();
#endif
if (!init_clutter (backend, error))
return FALSE;
meta_backend_post_init (backend);
return TRUE;
}
@@ -1044,6 +920,16 @@ meta_backend_init (MetaBackend *backend)
_backend = backend;
}
static void
meta_backend_post_init (MetaBackend *backend)
{
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
META_BACKEND_GET_CLASS (backend)->post_init (backend);
meta_settings_post_init (priv->settings);
}
/**
* meta_backend_get_idle_monitor: (skip)
*/
@@ -1375,6 +1261,54 @@ meta_backend_set_client_pointer_constraint (MetaBackend *backend,
priv->client_pointer_constraint = g_object_ref (constraint);
}
/* Mutter is responsible for pulling events off the X queue, so Clutter
* doesn't need (and shouldn't) run its normal event source which polls
* the X fd, but we do have to deal with dispatching events that accumulate
* in the clutter queue. This happens, for example, when clutter generate
* enter/leave events on mouse motion - several events are queued in the
* clutter queue but only one dispatched. It could also happen because of
* explicit calls to clutter_event_put(). We add a very simple custom
* event loop source which is simply responsible for pulling events off
* of the queue and dispatching them before we block for new events.
*/
static gboolean
event_prepare (GSource *source,
gint *timeout_)
{
*timeout_ = -1;
return clutter_events_pending ();
}
static gboolean
event_check (GSource *source)
{
return clutter_events_pending ();
}
static gboolean
event_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
ClutterEvent *event = clutter_event_get ();
if (event)
{
clutter_do_event (event);
clutter_event_free (event);
}
return TRUE;
}
static GSourceFuncs event_funcs = {
event_prepare,
event_check,
event_dispatch
};
ClutterBackend *
meta_backend_get_clutter_backend (MetaBackend *backend)
{
@@ -1389,6 +1323,14 @@ meta_backend_get_clutter_backend (MetaBackend *backend)
return priv->clutter_backend;
}
static ClutterBackend *
meta_get_clutter_backend (void)
{
MetaBackend *backend = meta_get_backend ();
return meta_backend_get_clutter_backend (backend);
}
void
meta_init_backend (GType backend_gtype)
{
@@ -1405,6 +1347,29 @@ meta_init_backend (GType backend_gtype)
}
}
/**
* meta_clutter_init: (skip)
*/
void
meta_clutter_init (void)
{
GSource *source;
clutter_set_custom_backend_func (meta_get_clutter_backend);
if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
{
g_warning ("Unable to initialize Clutter.\n");
exit (1);
}
source = g_source_new (&event_funcs, sizeof (GSource));
g_source_attach (source, NULL);
g_source_unref (source);
meta_backend_post_init (_backend);
}
/**
* meta_is_stage_views_enabled:
*

View File

@@ -84,7 +84,6 @@ translate_meta_cursor (MetaCursor cursor)
return "crosshair";
case META_CURSOR_IBEAM:
return "xterm";
case META_CURSOR_BLANK:
case META_CURSOR_NONE:
case META_CURSOR_LAST:
break;
@@ -94,48 +93,6 @@ translate_meta_cursor (MetaCursor cursor)
return NULL;
}
static Cursor
create_blank_cursor (Display *xdisplay)
{
Pixmap pixmap;
XColor color;
Cursor cursor;
XGCValues gc_values;
GC gc;
pixmap = XCreatePixmap (xdisplay, DefaultRootWindow (xdisplay), 1, 1, 1);
gc_values.foreground = BlackPixel (xdisplay, DefaultScreen (xdisplay));
gc = XCreateGC (xdisplay, pixmap, GCForeground, &gc_values);
XFillRectangle (xdisplay, pixmap, gc, 0, 0, 1, 1);
color.pixel = 0;
color.red = color.blue = color.green = 0;
cursor = XCreatePixmapCursor (xdisplay, pixmap, pixmap, &color, &color, 1, 1);
XFreeGC (xdisplay, gc);
XFreePixmap (xdisplay, pixmap);
return cursor;
}
static XcursorImages *
create_blank_cursor_images (void)
{
XcursorImages *images;
images = XcursorImagesCreate (1);
images->images[0] = XcursorImageCreate (1, 1);
images->images[0]->xhot = 0;
images->images[0]->yhot = 0;
memset (images->images[0]->pixels, 0, sizeof(int32_t));
return images;
}
MetaCursor
meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcursor)
{
@@ -146,18 +103,12 @@ Cursor
meta_create_x_cursor (Display *xdisplay,
MetaCursor cursor)
{
if (cursor == META_CURSOR_BLANK)
return create_blank_cursor (xdisplay);
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
}
static XcursorImages *
load_cursor_on_client (MetaCursor cursor, int scale)
{
if (cursor == META_CURSOR_BLANK)
return create_blank_cursor_images ();
return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
meta_prefs_get_cursor_theme (),
meta_prefs_get_cursor_size () * scale);

View File

@@ -54,8 +54,8 @@ meta_input_device_init (MetaInputDevice *input_device)
static void
meta_input_device_constructed (GObject *object)
{
MetaInputDevice *input_device = META_INPUT_DEVICE (object);
#ifdef HAVE_LIBWACOM
MetaInputDevice *input_device;
WacomDeviceDatabase *wacom_db;
MetaInputDevicePrivate *priv;
const char *node;
@@ -64,7 +64,6 @@ meta_input_device_constructed (GObject *object)
G_OBJECT_CLASS (meta_input_device_parent_class)->constructed (object);
#ifdef HAVE_LIBWACOM
input_device = META_INPUT_DEVICE (object);
priv = meta_input_device_get_instance_private (input_device);
wacom_db = meta_backend_get_wacom_database (meta_get_backend ());
node = clutter_input_device_get_device_node (CLUTTER_INPUT_DEVICE (input_device));

View File

@@ -35,6 +35,7 @@ typedef struct _MetaMapperInputInfo MetaMapperInputInfo;
typedef struct _MetaMapperOutputInfo MetaMapperOutputInfo;
typedef struct _MappingHelper MappingHelper;
typedef struct _DeviceCandidates DeviceCandidates;
typedef struct _DeviceMatch DeviceMatch;
struct _MetaInputMapper
{
@@ -59,11 +60,11 @@ typedef enum
typedef enum
{
META_MATCH_IS_BUILTIN, /* Output is builtin, applies mainly to system-integrated devices */
META_MATCH_SIZE, /* Size from input device and output match */
META_MATCH_EDID_FULL, /* Full EDID model match, eg. "Cintiq 12WX" */
META_MATCH_EDID_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */
META_MATCH_EDID_VENDOR, /* EDID vendor match, eg. "WAC" for Wacom */
META_MATCH_EDID_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */
META_MATCH_EDID_FULL, /* Full EDID model match, eg. "Cintiq 12WX" */
META_MATCH_SIZE, /* Size from input device and output match */
META_MATCH_IS_BUILTIN, /* Output is builtin, applies mainly to system-integrated devices */
N_OUTPUT_MATCHES
} MetaOutputMatchType;
@@ -87,13 +88,19 @@ struct _MappingHelper
GArray *device_maps;
};
struct _DeviceMatch
{
MetaMonitor *monitor;
uint32_t score;
};
struct _DeviceCandidates
{
MetaMapperInputInfo *input;
MetaMonitor *candidates[N_OUTPUT_MATCHES];
GArray *matches; /* Array of DeviceMatch */;
MetaOutputMatchType best;
int best;
};
enum
@@ -305,52 +312,37 @@ input_device_get_physical_size (MetaInputMapper *mapper,
}
static gboolean
find_size_match (MetaMapperInputInfo *input,
GList *monitors,
MetaMonitor **matched_monitor)
match_size (MetaMapperInputInfo *input,
MetaMonitor *monitor)
{
double min_w_diff, min_h_diff;
double w_diff, h_diff;
int o_width, o_height;
double i_width, i_height;
gboolean found = FALSE;
GList *l;
min_w_diff = min_h_diff = MAX_SIZE_MATCH_DIFF;
if (!input_device_get_physical_size (input->mapper, input->device,
&i_width, &i_height))
return FALSE;
for (l = monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
double w_diff, h_diff;
int o_width, o_height;
meta_monitor_get_physical_dimensions (monitor, &o_width, &o_height);
w_diff = ABS (1 - ((double) o_width / i_width));
h_diff = ABS (1 - ((double) o_height / i_height));
meta_monitor_get_physical_dimensions (monitor, &o_width, &o_height);
w_diff = ABS (1 - ((double) o_width / i_width));
h_diff = ABS (1 - ((double) o_height / i_height));
if (w_diff >= min_w_diff || h_diff >= min_h_diff)
continue;
*matched_monitor = monitor;
min_w_diff = w_diff;
min_h_diff = h_diff;
found = TRUE;
}
return found;
return w_diff < MAX_SIZE_MATCH_DIFF && h_diff < MAX_SIZE_MATCH_DIFF;
}
static gboolean
find_builtin_output (MetaInputMapper *mapper,
MetaMonitor **matched_monitor)
match_builtin (MetaInputMapper *mapper,
MetaMonitor *monitor)
{
MetaMonitor *panel;
return monitor == meta_monitor_manager_get_laptop_panel (mapper->monitor_manager);
}
panel = meta_monitor_manager_get_laptop_panel (mapper->monitor_manager);
*matched_monitor = panel;
return panel != NULL;
static int
sort_by_score (DeviceMatch *match1,
DeviceMatch *match2)
{
return (int) match1->score - match2->score;
}
static void
@@ -358,36 +350,45 @@ guess_candidates (MetaInputMapper *mapper,
MetaMapperInputInfo *input,
DeviceCandidates *info)
{
MetaOutputMatchType best = N_OUTPUT_MATCHES;
GList *monitors, *l;
MetaMonitor *matched_monitor = NULL;
monitors = meta_monitor_manager_get_monitors (mapper->monitor_manager);
for (l = monitors; l; l = l->next)
{
MetaOutputMatchType edid_match;
DeviceMatch match = { l->data, 0 };
if (match_edid (input, l->data, &edid_match))
{
best = MIN (best, edid_match);
info->candidates[edid_match] = l->data;
}
match.score |= 1 << edid_match;
if (match_size (input, l->data))
match.score |= 1 << META_MATCH_SIZE;
if (input->builtin && match_builtin (mapper, l->data))
match.score |= 1 << META_MATCH_IS_BUILTIN;
if (match.score > 0)
g_array_append_val (info->matches, match);
}
if (find_size_match (input, monitors, &matched_monitor))
if (info->matches->len == 0)
{
best = MIN (best, META_MATCH_SIZE);
info->candidates[META_MATCH_SIZE] = matched_monitor;
}
DeviceMatch match = { 0 };
if (input->builtin || best == N_OUTPUT_MATCHES)
match.monitor =
meta_monitor_manager_get_laptop_panel (mapper->monitor_manager);
g_array_append_val (info->matches, match);
info->best = 0;
}
else
{
best = MIN (best, META_MATCH_IS_BUILTIN);
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
}
DeviceMatch *best;
info->best = best;
g_array_sort (info->matches, (GCompareFunc) sort_by_score);
best = &g_array_index (info->matches, DeviceMatch, 0);
info->best = best->score;
}
}
static void
@@ -399,6 +400,7 @@ mapping_helper_add (MappingHelper *helper,
guint i, pos = 0;
info.input = input;
info.matches = g_array_new (FALSE, TRUE, sizeof (DeviceMatch));
guess_candidates (mapper, input, &info);
@@ -408,7 +410,7 @@ mapping_helper_add (MappingHelper *helper,
elem = &g_array_index (helper->device_maps, DeviceCandidates, i);
if (elem->best < info.best)
if (elem->best > info.best)
pos = i;
}
@@ -422,26 +424,32 @@ static void
mapping_helper_apply (MappingHelper *helper,
MetaInputMapper *mapper)
{
guint i;
guint i, j;
/* Now, decide which input claims which output */
for (i = 0; i < helper->device_maps->len; i++)
{
MetaMapperOutputInfo *output;
DeviceCandidates *info;
MetaOutputMatchType j;
MetaMonitor *monitor;
info = &g_array_index (helper->device_maps, DeviceCandidates, i);
g_debug ("Applying mapping %d to input device '%s', capabilities %x", i,
clutter_input_device_get_device_name (info->input->device),
mapper_input_info_get_caps (info->input));
for (j = 0; j < N_OUTPUT_MATCHES; j++)
for (j = 0; j < info->matches->len; j++)
{
MetaLogicalMonitor *logical_monitor;
DeviceMatch *match;
if (!info->candidates[j])
continue;
match = &g_array_index (info->matches, DeviceMatch, j);
g_debug ("Output candidate '%s', score %x",
meta_monitor_get_display_name (match->monitor),
match->score);
logical_monitor =
meta_monitor_get_logical_monitor (info->candidates[j]);
monitor = match->monitor;
logical_monitor = meta_monitor_get_logical_monitor (monitor);
output = g_hash_table_lookup (mapper->output_devices,
logical_monitor);
@@ -451,8 +459,10 @@ mapping_helper_apply (MappingHelper *helper,
if (output->attached_caps & mapper_input_info_get_caps (info->input))
continue;
mapper_output_info_add_input (output, info->input,
info->candidates[j]);
g_debug ("Matched input '%s' with output '%s'",
clutter_input_device_get_device_name (info->input->device),
meta_monitor_get_display_name (match->monitor));
mapper_output_info_add_input (output, info->input, monitor);
break;
}
}

View File

@@ -90,7 +90,6 @@ float meta_logical_monitor_get_scale (MetaLogicalMonitor *logical_monitor);
MetaMonitorTransform meta_logical_monitor_get_transform (MetaLogicalMonitor *logical_monitor);
META_EXPORT_TEST
MetaRectangle meta_logical_monitor_get_layout (MetaLogicalMonitor *logical_monitor);
META_EXPORT_TEST

View File

@@ -172,7 +172,6 @@ assign_monitor_crtc (MetaMonitor *monitor,
MetaCrtc *crtc;
MetaMonitorTransform transform;
MetaMonitorTransform crtc_transform;
MetaMonitorTransform crtc_hw_transform;
int crtc_x, crtc_y;
float x_offset, y_offset;
float scale = 0.0;
@@ -201,12 +200,10 @@ assign_monitor_crtc (MetaMonitor *monitor,
transform = data->logical_monitor_config->transform;
crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
if (meta_monitor_manager_is_transform_handled (data->monitor_manager,
crtc,
crtc_transform))
crtc_hw_transform = crtc_transform;
else
crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL;
if (!meta_monitor_manager_is_transform_handled (data->monitor_manager,
crtc,
crtc_transform))
crtc_transform = META_MONITOR_TRANSFORM_NORMAL;
meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
&crtc_x, &crtc_y);
@@ -247,7 +244,7 @@ assign_monitor_crtc (MetaMonitor *monitor,
.crtc = crtc,
.mode = crtc_mode,
.layout = crtc_layout,
.transform = crtc_hw_transform,
.transform = crtc_transform,
.outputs = g_ptr_array_new ()
};
g_ptr_array_add (crtc_info->outputs, output);
@@ -446,35 +443,23 @@ MetaMonitorsConfigKey *
meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager)
{
MetaMonitorsConfigKey *config_key;
MetaMonitorSpec *laptop_monitor_spec;
GList *l;
GList *monitor_specs;
laptop_monitor_spec = NULL;
monitor_specs = NULL;
for (l = monitor_manager->monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
MetaMonitorSpec *monitor_spec;
if (meta_monitor_is_laptop_panel (monitor))
{
laptop_monitor_spec = meta_monitor_get_spec (monitor);
if (is_lid_closed (monitor_manager))
continue;
}
if (meta_monitor_is_laptop_panel (monitor) &&
is_lid_closed (monitor_manager))
continue;
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
}
if (!monitor_specs && laptop_monitor_spec)
{
monitor_specs =
g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec));
}
if (!monitor_specs)
return NULL;

View File

@@ -49,10 +49,9 @@ meta_monitor_transform_is_rotated (MetaMonitorTransform transform)
static inline gboolean
meta_monitor_transform_is_flipped (MetaMonitorTransform transform)
{
return (transform >= META_MONITOR_TRANSFORM_FLIPPED);
return (abs(transform) >= META_MONITOR_TRANSFORM_FLIPPED);
}
META_EXPORT_TEST
MetaMonitorTransform meta_monitor_transform_invert (MetaMonitorTransform transform);
META_EXPORT_TEST

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