Compare commits
131 Commits
wip/carlos
...
wip/exalm/
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0c03702168 | ||
![]() |
03514bb31a | ||
![]() |
697b84e80e | ||
![]() |
5fd90e85ed | ||
![]() |
30d9d1968c | ||
![]() |
65aa476414 | ||
![]() |
03d177cf64 | ||
![]() |
dfa235aa5d | ||
![]() |
d722e59aac | ||
![]() |
32dbcd9352 | ||
![]() |
3a474556b8 | ||
![]() |
249274c677 | ||
![]() |
ae83a61e67 | ||
![]() |
826573ccce | ||
![]() |
dbff32ec5c | ||
![]() |
2f1f47d257 | ||
![]() |
06781985e4 | ||
![]() |
5b0a7b3a33 | ||
![]() |
1ecdaa646f | ||
![]() |
2f4d50c723 | ||
![]() |
4b8bb4608c | ||
![]() |
aa34f6ad7c | ||
![]() |
f9be670522 | ||
![]() |
d77bcb9028 | ||
![]() |
d29c8e290c | ||
![]() |
e12ce70385 | ||
![]() |
442f34b4de | ||
![]() |
20becd782f | ||
![]() |
feb8bfa0bf | ||
![]() |
59a38fcb69 | ||
![]() |
190e285c23 | ||
![]() |
a9a9a0d1c5 | ||
![]() |
57a2f7b4a3 | ||
![]() |
1f895719b3 | ||
![]() |
37326e4a32 | ||
![]() |
8cff3b84f7 | ||
![]() |
578c30792a | ||
![]() |
9daec23033 | ||
![]() |
5f729ea437 | ||
![]() |
ae7cc0417f | ||
![]() |
468bf81307 | ||
![]() |
551101c65c | ||
![]() |
110ed7ff8a | ||
![]() |
2afe3e9223 | ||
![]() |
de99dd7eb6 | ||
![]() |
34be97d855 | ||
![]() |
1de436684c | ||
![]() |
847e89d31f | ||
![]() |
f9eb140e62 | ||
![]() |
3aff755048 | ||
![]() |
2e358f3c43 | ||
![]() |
c00a8e98a3 | ||
![]() |
2a6e8bda8d | ||
![]() |
31a3b1b4c5 | ||
![]() |
ff65c95aee | ||
![]() |
f086eafe57 | ||
![]() |
bb73038a27 | ||
![]() |
2b95ec40c6 | ||
![]() |
203c20d7ad | ||
![]() |
ff5f77f273 | ||
![]() |
fc0b8f9d9c | ||
![]() |
1e284c601c | ||
![]() |
5e7ce7ea75 | ||
![]() |
69d0ff4567 | ||
![]() |
3944daf3c0 | ||
![]() |
b45cea301e | ||
![]() |
14dfe929f2 | ||
![]() |
b9a52ecfdf | ||
![]() |
feb444402e | ||
![]() |
9ed463b488 | ||
![]() |
33450700dc | ||
![]() |
62f251574f | ||
![]() |
59eebd6f6d | ||
![]() |
ca82cde6dd | ||
![]() |
9b054f4a1b | ||
![]() |
f31a7acab5 | ||
![]() |
a0d87662f7 | ||
![]() |
c302f4d379 | ||
![]() |
3c4efd13c1 | ||
![]() |
9676db4dbf | ||
![]() |
a132c8dc8e | ||
![]() |
cae5b99537 | ||
![]() |
6ffdfff9ee | ||
![]() |
b18d4fc346 | ||
![]() |
7e27fb6d56 | ||
![]() |
8f96885af8 | ||
![]() |
51ee41ee43 | ||
![]() |
e743b36cfc | ||
![]() |
96a108ed4e | ||
![]() |
da633dcc52 | ||
![]() |
86646679f1 | ||
![]() |
df4eeff6f2 | ||
![]() |
64304b0b68 | ||
![]() |
c5159e3184 | ||
![]() |
280429bac8 | ||
![]() |
98df2dbd05 | ||
![]() |
4a72ac0516 | ||
![]() |
802b24a640 | ||
![]() |
162aec7802 | ||
![]() |
9823a0f6c9 | ||
![]() |
b8524504f4 | ||
![]() |
c1933cfd09 | ||
![]() |
1142f06af5 | ||
![]() |
bb4e87bf35 | ||
![]() |
37256cb76b | ||
![]() |
7f12099ead | ||
![]() |
88141f1483 | ||
![]() |
7146a6dddb | ||
![]() |
dbce29a0ae | ||
![]() |
031098a43d | ||
![]() |
dc4cb562b7 | ||
![]() |
2e086c74e7 | ||
![]() |
e884ba7f39 | ||
![]() |
2802d359e5 | ||
![]() |
d54b10b366 | ||
![]() |
d4993c4b22 | ||
![]() |
ae49f89cf3 | ||
![]() |
ce3e293a18 | ||
![]() |
8d83dec044 | ||
![]() |
d4953c77c3 | ||
![]() |
237f277641 | ||
![]() |
59e454f01e | ||
![]() |
0b4cf9c65f | ||
![]() |
82b710688b | ||
![]() |
387a13f0ab | ||
![]() |
e5542c3210 | ||
![]() |
d85c3c1e94 | ||
![]() |
d830d985c1 | ||
![]() |
4c0aa2afca | ||
![]() |
d6af59612c | ||
![]() |
be59b514ca |
27
NEWS
27
NEWS
@@ -1,3 +1,30 @@
|
||||
3.37.3
|
||||
======
|
||||
* Support custom keyboard layouts in $XDG_CONFIG_HOME/xkb [Peter; !936]
|
||||
* Optimize resource scale computation [Jonas D.; !1196, !1276, !1343]
|
||||
* Allow animating ClutterActor's content property [Georges; !1301]
|
||||
* Implement backgrounds as ClutterContent [Georges; !1302]
|
||||
* Add ClutterAlignContraint:pivot-point property [Jonas D.; !737]
|
||||
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
|
||||
* Do not paint textures of fully obscured windows [Robert; !1326]
|
||||
* Use a more appropriate combine function on opaque areas [Daniel; !1331]
|
||||
* Fix remote desktop being broken without screencast session [Olivier; #1307]
|
||||
* Remove more long-deprecated Clutter APIs [Adam, Georges; !1194, !1332]
|
||||
* Drive each monitor by its own frame clock [Jonas Å.; !1285]
|
||||
* Fix copy/paste failures on X11 [Carlos; !1350]
|
||||
* Mipmap background texture rendering [Daniel; !1347]
|
||||
* Plugged memory leaks [Sebastian, Jonas D.; !1293, !1281, !1304]
|
||||
* Misc. bug fixes and cleanups [Jonas Å., Jonas D., Daniel, Corentin, Carlos,
|
||||
Sebastian, Michel, Robert, Florian; !1288, !1289, !1291, !1296, !1292, !1298,
|
||||
!1300, !1303, !1290, !1287, !1306, !1305, !1308, !1313, !1250, !1314, !1267,
|
||||
!1275, !1317, !1270, !1322, !1181, !1282, !1325, !1323, !1240, !1295, !1329,
|
||||
!1333, !1334, !1336, !1341, #1312, !1345, !1349, !1356, #873, !1310, !1357]
|
||||
|
||||
Contributors:
|
||||
Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho,
|
||||
Peter Hutterer, Adam Jackson, Sebastian Keller, Robert Mader, Florian Müllner,
|
||||
Georges Basile Stavracas Neto, Corentin Noël, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
3.37.2
|
||||
======
|
||||
* Fix move-to-center keybinding with multiple monitors [Sergey; #1073]
|
||||
|
@@ -1,147 +0,0 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Based on GailContainer from GAIL
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:cally-group
|
||||
* @Title: CallyGroup
|
||||
* @short_description: Implementation of the ATK interfaces for a #ClutterGroup
|
||||
* @see_also: #ClutterGroup
|
||||
*
|
||||
* #CallyGroup implements the required ATK interfaces of #ClutterGroup
|
||||
* In particular it exposes each of the Clutter actors contained in the
|
||||
* group.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "cally-group.h"
|
||||
#include "cally-actor-private.h"
|
||||
|
||||
static gint cally_group_get_n_children (AtkObject *obj);
|
||||
static AtkObject* cally_group_ref_child (AtkObject *obj,
|
||||
gint i);
|
||||
static void cally_group_real_initialize (AtkObject *obj,
|
||||
gpointer data);
|
||||
|
||||
G_DEFINE_TYPE (CallyGroup, cally_group, CALLY_TYPE_ACTOR)
|
||||
|
||||
static void
|
||||
cally_group_class_init (CallyGroupClass *klass)
|
||||
{
|
||||
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
class->get_n_children = cally_group_get_n_children;
|
||||
class->ref_child = cally_group_ref_child;
|
||||
class->initialize = cally_group_real_initialize;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_group_init (CallyGroup *group)
|
||||
{
|
||||
/* nothing to do yet */
|
||||
}
|
||||
|
||||
/**
|
||||
* cally_group_new:
|
||||
* @actor: a #ClutterGroup
|
||||
*
|
||||
* Creates a #CallyGroup for @actor
|
||||
*
|
||||
* Return value: the newly created #CallyGroup
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
AtkObject *
|
||||
cally_group_new (ClutterActor *actor)
|
||||
{
|
||||
GObject *object = NULL;
|
||||
AtkObject *accessible = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_GROUP (actor), NULL);
|
||||
|
||||
object = g_object_new (CALLY_TYPE_GROUP, NULL);
|
||||
|
||||
accessible = ATK_OBJECT (object);
|
||||
atk_object_initialize (accessible, actor);
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static gint
|
||||
cally_group_get_n_children (AtkObject *obj)
|
||||
{
|
||||
ClutterActor *actor = NULL;
|
||||
gint count = 0;
|
||||
|
||||
g_return_val_if_fail (CALLY_IS_GROUP (obj), count);
|
||||
|
||||
actor = CALLY_GET_CLUTTER_ACTOR (obj);
|
||||
|
||||
if (actor == NULL) /* defunct */
|
||||
return 0;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_GROUP(actor), count);
|
||||
|
||||
count = clutter_actor_get_n_children (actor);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static AtkObject*
|
||||
cally_group_ref_child (AtkObject *obj,
|
||||
gint i)
|
||||
{
|
||||
AtkObject *accessible = NULL;
|
||||
ClutterActor *actor = NULL;
|
||||
ClutterActor *child = NULL;
|
||||
|
||||
g_return_val_if_fail (CALLY_IS_GROUP (obj), NULL);
|
||||
g_return_val_if_fail ((i >= 0), NULL);
|
||||
|
||||
actor = CALLY_GET_CLUTTER_ACTOR (obj);
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_GROUP(actor), NULL);
|
||||
child = clutter_actor_get_child_at_index (actor, i);
|
||||
|
||||
if (!child)
|
||||
return NULL;
|
||||
|
||||
accessible = clutter_actor_get_accessible (child);
|
||||
|
||||
if (accessible != NULL)
|
||||
g_object_ref (accessible);
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_group_real_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
ATK_OBJECT_CLASS (cally_group_parent_class)->initialize (obj, data);
|
||||
|
||||
obj->role = ATK_ROLE_PANEL;
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2008 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* Based on GailContainer from GAIL
|
||||
* Copyright 2001, 2002, 2003 Sun Microsystems Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CALLY_GROUP_H__
|
||||
#define __CALLY_GROUP_H__
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <cally/cally-actor.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_GROUP (cally_group_get_type ())
|
||||
#define CALLY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_GROUP, CallyGroup))
|
||||
#define CALLY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_GROUP, CallyGroupClass))
|
||||
#define CALLY_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_GROUP))
|
||||
#define CALLY_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_GROUP))
|
||||
#define CALLY_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_GROUP, CallyGroupClass))
|
||||
|
||||
typedef struct _CallyGroup CallyGroup;
|
||||
typedef struct _CallyGroupClass CallyGroupClass;
|
||||
typedef struct _CallyGroupPrivate CallyGroupPrivate;
|
||||
|
||||
/**
|
||||
* CallyGroup:
|
||||
*
|
||||
* The <structname>CallyGroup</structname> structure contains only
|
||||
* private data and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
struct _CallyGroup
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActor parent;
|
||||
|
||||
CallyGroupPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* CallyGroupClass:
|
||||
*
|
||||
* The <structname>CallyGroupClass</structname> structure contains only
|
||||
* private data
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
struct _CallyGroupClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
gpointer _padding_dummy[8];
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType cally_group_get_type (void) G_GNUC_CONST;
|
||||
CLUTTER_EXPORT
|
||||
AtkObject* cally_group_new (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CALLY_GROUP_H__ */
|
@@ -1,98 +0,0 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:cally-rectangle
|
||||
* @short_description: Implementation of the ATK interfaces for a #ClutterRectangle
|
||||
* @see_also: #ClutterRectangle
|
||||
*
|
||||
* #CallyRectangle implements the required ATK interfaces of #ClutterRectangle
|
||||
*
|
||||
* In particular it sets a proper role for the rectangle.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
#include "cally-rectangle.h"
|
||||
#include "cally-actor-private.h"
|
||||
|
||||
#include "clutter-color.h"
|
||||
#include "deprecated/clutter-rectangle.h"
|
||||
|
||||
/* AtkObject */
|
||||
static void cally_rectangle_real_initialize (AtkObject *obj,
|
||||
gpointer data);
|
||||
|
||||
G_DEFINE_TYPE (CallyRectangle, cally_rectangle, CALLY_TYPE_ACTOR)
|
||||
|
||||
static void
|
||||
cally_rectangle_class_init (CallyRectangleClass *klass)
|
||||
{
|
||||
/* GObjectClass *gobject_class = G_OBJECT_CLASS (klass); */
|
||||
AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
|
||||
|
||||
class->initialize = cally_rectangle_real_initialize;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_rectangle_init (CallyRectangle *rectangle)
|
||||
{
|
||||
/* nothing to do yet */
|
||||
}
|
||||
|
||||
/**
|
||||
* cally_rectangle_new:
|
||||
* @actor: a #ClutterActor
|
||||
*
|
||||
* Creates a new #CallyRectangle for the given @actor. @actor must be
|
||||
* a #ClutterRectangle.
|
||||
*
|
||||
* Return value: the newly created #AtkObject
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
AtkObject*
|
||||
cally_rectangle_new (ClutterActor *actor)
|
||||
{
|
||||
GObject *object = NULL;
|
||||
AtkObject *accessible = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_RECTANGLE (actor), NULL);
|
||||
|
||||
object = g_object_new (CALLY_TYPE_RECTANGLE, NULL);
|
||||
|
||||
accessible = ATK_OBJECT (object);
|
||||
atk_object_initialize (accessible, actor);
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
static void
|
||||
cally_rectangle_real_initialize (AtkObject *obj,
|
||||
gpointer data)
|
||||
{
|
||||
ATK_OBJECT_CLASS (cally_rectangle_parent_class)->initialize (obj, data);
|
||||
|
||||
obj->role = ATK_ROLE_IMAGE;
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
/* CALLY - The Clutter Accessibility Implementation Library
|
||||
*
|
||||
* Copyright (C) 2009 Igalia, S.L.
|
||||
*
|
||||
* Author: Alejandro Piñeiro Iglesias <apinheiro@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CALLY_RECTANGLE_H__
|
||||
#define __CALLY_RECTANGLE_H__
|
||||
|
||||
#if !defined(__CALLY_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <cally/cally-actor.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CALLY_TYPE_RECTANGLE (cally_rectangle_get_type ())
|
||||
#define CALLY_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CALLY_TYPE_RECTANGLE, CallyRectangle))
|
||||
#define CALLY_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CALLY_TYPE_RECTANGLE, CallyRectangleClass))
|
||||
#define CALLY_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CALLY_TYPE_RECTANGLE))
|
||||
#define CALLY_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CALLY_TYPE_RECTANGLE))
|
||||
#define CALLY_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CALLY_TYPE_RECTANGLE, CallyRectangleClass))
|
||||
|
||||
typedef struct _CallyRectangle CallyRectangle;
|
||||
typedef struct _CallyRectangleClass CallyRectangleClass;
|
||||
typedef struct _CallyRectanglePrivate CallyRectanglePrivate;
|
||||
|
||||
/**
|
||||
* CallyRectangle:
|
||||
*
|
||||
* The <structname>CallyRectangle</structname> structure contains only private
|
||||
* data and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
struct _CallyRectangle
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActor parent;
|
||||
|
||||
CallyRectanglePrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* CallyRectangleClass:
|
||||
*
|
||||
* The <structname>CallyRectangleClass</structname> structure contains
|
||||
* only private data
|
||||
*
|
||||
* Since: 1.4
|
||||
*/
|
||||
struct _CallyRectangleClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
gpointer _padding_dummy[8];
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType cally_rectangle_get_type (void) G_GNUC_CONST;
|
||||
CLUTTER_EXPORT
|
||||
AtkObject* cally_rectangle_new (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CALLY_RECTANGLE_H__ */
|
@@ -63,7 +63,7 @@ struct _CallyStagePrivate
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (CallyStage,
|
||||
cally_stage,
|
||||
CALLY_TYPE_GROUP,
|
||||
CALLY_TYPE_ACTOR,
|
||||
G_ADD_PRIVATE (CallyStage)
|
||||
G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
|
||||
cally_stage_window_interface_init));
|
||||
|
@@ -25,7 +25,7 @@
|
||||
#error "Only <cally/cally.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <cally/cally-group.h>
|
||||
#include <cally/cally-actor.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -52,7 +52,7 @@ typedef struct _CallyStagePrivate CallyStagePrivate;
|
||||
struct _CallyStage
|
||||
{
|
||||
/*< private >*/
|
||||
CallyGroup parent;
|
||||
CallyActor parent;
|
||||
|
||||
CallyStagePrivate *priv;
|
||||
};
|
||||
@@ -68,7 +68,7 @@ struct _CallyStage
|
||||
struct _CallyStageClass
|
||||
{
|
||||
/*< private >*/
|
||||
CallyGroupClass parent_class;
|
||||
CallyActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
gpointer _padding_dummy[16];
|
||||
|
@@ -36,10 +36,8 @@
|
||||
#include "cally.h"
|
||||
|
||||
#include "cally-actor.h"
|
||||
#include "cally-group.h"
|
||||
#include "cally-stage.h"
|
||||
#include "cally-text.h"
|
||||
#include "cally-rectangle.h"
|
||||
#include "cally-clone.h"
|
||||
|
||||
#include "cally-factory.h"
|
||||
@@ -52,10 +50,8 @@
|
||||
|
||||
/* factories initialization*/
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_ACTOR, cally_actor, cally_actor_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_GROUP, cally_group, cally_group_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_STAGE, cally_stage, cally_stage_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_TEXT, cally_text, cally_text_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_RECTANGLE, cally_rectangle, cally_rectangle_new)
|
||||
CALLY_ACCESSIBLE_FACTORY (CALLY_TYPE_CLONE, cally_clone, cally_clone_new)
|
||||
|
||||
/**
|
||||
@@ -73,10 +69,8 @@ cally_accessibility_init (void)
|
||||
{
|
||||
/* setting the factories */
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_ACTOR, cally_actor);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_GROUP, cally_group);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_STAGE, cally_stage);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_TEXT, cally_text);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_RECTANGLE, cally_rectangle);
|
||||
CALLY_ACTOR_SET_FACTORY (CLUTTER_TYPE_CLONE, cally_clone);
|
||||
|
||||
/* Initialize the CallyUtility class */
|
||||
|
@@ -26,9 +26,7 @@
|
||||
#include "cally-actor.h"
|
||||
#include "cally-clone.h"
|
||||
#include "cally-factory.h"
|
||||
#include "cally-group.h"
|
||||
#include "cally-main.h"
|
||||
#include "cally-rectangle.h"
|
||||
#include "cally-root.h"
|
||||
#include "cally-stage.h"
|
||||
#include "cally-text.h"
|
||||
|
@@ -110,35 +110,12 @@ typedef ClutterActorTraverseVisitFlags (*ClutterTraverseCallback) (ClutterActor
|
||||
typedef gboolean (*ClutterForeachCallback) (ClutterActor *actor,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _AnchorCoord AnchorCoord;
|
||||
typedef struct _SizeRequest SizeRequest;
|
||||
|
||||
typedef struct _ClutterLayoutInfo ClutterLayoutInfo;
|
||||
typedef struct _ClutterTransformInfo ClutterTransformInfo;
|
||||
typedef struct _ClutterAnimationInfo ClutterAnimationInfo;
|
||||
|
||||
/* Internal helper struct to represent a point that can be stored in
|
||||
either direct pixel coordinates or as a fraction of the actor's
|
||||
size. It is used for the anchor point, scale center and rotation
|
||||
centers. */
|
||||
struct _AnchorCoord
|
||||
{
|
||||
gboolean is_fractional;
|
||||
|
||||
union
|
||||
{
|
||||
/* Used when is_fractional == TRUE */
|
||||
struct
|
||||
{
|
||||
gdouble x;
|
||||
gdouble y;
|
||||
} fraction;
|
||||
|
||||
/* Use when is_fractional == FALSE */
|
||||
graphene_point3d_t units;
|
||||
} v;
|
||||
};
|
||||
|
||||
struct _SizeRequest
|
||||
{
|
||||
guint age;
|
||||
@@ -183,24 +160,15 @@ ClutterLayoutInfo * _clutter_actor_peek_layout_info
|
||||
|
||||
struct _ClutterTransformInfo
|
||||
{
|
||||
/* rotation (angle and center) */
|
||||
/* rotation */
|
||||
gdouble rx_angle;
|
||||
AnchorCoord rx_center;
|
||||
|
||||
gdouble ry_angle;
|
||||
AnchorCoord ry_center;
|
||||
|
||||
gdouble rz_angle;
|
||||
AnchorCoord rz_center;
|
||||
|
||||
/* scaling */
|
||||
gdouble scale_x;
|
||||
gdouble scale_y;
|
||||
gdouble scale_z;
|
||||
AnchorCoord scale_center;
|
||||
|
||||
/* anchor point */
|
||||
AnchorCoord anchor;
|
||||
|
||||
/* translation */
|
||||
graphene_point3d_t translation;
|
||||
@@ -315,13 +283,15 @@ void _clutter_actor_queue_relayout_on_clones
|
||||
void _clutter_actor_queue_only_relayout (ClutterActor *actor);
|
||||
void clutter_actor_clear_stage_views_recursive (ClutterActor *actor);
|
||||
|
||||
gboolean _clutter_actor_get_real_resource_scale (ClutterActor *actor,
|
||||
float *resource_scale);
|
||||
float clutter_actor_get_real_resource_scale (ClutterActor *actor);
|
||||
|
||||
ClutterPaintNode * clutter_actor_create_texture_paint_node (ClutterActor *self,
|
||||
CoglTexture *texture);
|
||||
|
||||
void clutter_actor_update_stage_views (ClutterActor *self);
|
||||
void clutter_actor_update_stage_views (ClutterActor *self,
|
||||
int phase);
|
||||
|
||||
void clutter_actor_queue_immediate_relayout (ClutterActor *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -142,11 +142,6 @@ struct _ClutterActor
|
||||
* ClutterActorClass:
|
||||
* @show: signal class handler for #ClutterActor::show; it must chain
|
||||
* up to the parent's implementation
|
||||
* @show_all: virtual function for containers and composite actors, to
|
||||
* determine which children should be shown when calling
|
||||
* clutter_actor_show_all() on the actor. Defaults to calling
|
||||
* clutter_actor_show(). This virtual function is deprecated and it
|
||||
* should not be overridden.
|
||||
* @hide: signal class handler for #ClutterActor::hide; it must chain
|
||||
* up to the parent's implementation
|
||||
* @hide_all: virtual function for containers and composite actors, to
|
||||
@@ -183,7 +178,10 @@ struct _ClutterActor
|
||||
* implementation.
|
||||
* @apply_transform: virtual function, used when applying the transformations
|
||||
* to an actor before painting it or when transforming coordinates or
|
||||
* the allocation; it must chain up to the parent's implementation
|
||||
* the allocation; if the transformation calculated by this function may
|
||||
* have changed, the cached transformation must be invalidated by calling
|
||||
* clutter_actor_invalidate_transform(); it must chain up to the parent's
|
||||
* implementation
|
||||
* @parent_set: signal class handler for the #ClutterActor::parent-set
|
||||
* @destroy: signal class handler for #ClutterActor::destroy. It must
|
||||
* chain up to the parent's implementation
|
||||
@@ -226,7 +224,6 @@ struct _ClutterActorClass
|
||||
|
||||
/*< public >*/
|
||||
void (* show) (ClutterActor *self);
|
||||
void (* show_all) (ClutterActor *self);
|
||||
void (* hide) (ClutterActor *self);
|
||||
void (* hide_all) (ClutterActor *self);
|
||||
void (* realize) (ClutterActor *self);
|
||||
@@ -302,6 +299,9 @@ struct _ClutterActorClass
|
||||
gboolean (* touch_event) (ClutterActor *self,
|
||||
ClutterTouchEvent *event);
|
||||
gboolean (* has_accessible) (ClutterActor *self);
|
||||
void (* resource_scale_changed) (ClutterActor *self);
|
||||
float (* calculate_resource_scale) (ClutterActor *self,
|
||||
int phase);
|
||||
|
||||
/*< private >*/
|
||||
/* padding for future expansion */
|
||||
@@ -419,7 +419,9 @@ CLUTTER_EXPORT
|
||||
void clutter_actor_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self);
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self,
|
||||
float x,
|
||||
float y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_allocate_available_size (ClutterActor *self,
|
||||
gfloat x,
|
||||
@@ -454,6 +456,10 @@ void clutter_actor_set_position
|
||||
gfloat x,
|
||||
gfloat y);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_fixed_position (ClutterActor *self,
|
||||
float *x,
|
||||
float *y);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_get_position (ClutterActor *self,
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
@@ -593,8 +599,7 @@ gboolean clutter_actor_get_paint_box
|
||||
ClutterActorBox *box);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_get_resource_scale (ClutterActor *self,
|
||||
gfloat *resource_scale);
|
||||
float clutter_actor_get_resource_scale (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_has_overlaps (ClutterActor *self);
|
||||
@@ -922,6 +927,12 @@ void clutter_actor_pick_box (ClutterActor *self,
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_actor_peek_stage_views (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_actor_invalidate_transform (ClutterActor *self);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_actor_pick_frame_clock (ClutterActor *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_H__ */
|
||||
|
@@ -194,3 +194,25 @@ clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
|
||||
else
|
||||
return clutter_interval_compute_value (interval, progress, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animatable_get_actor:
|
||||
* @animatable: a #ClutterAnimatable
|
||||
*
|
||||
* Get animated actor.
|
||||
*
|
||||
* Return value: (transfer none): a #ClutterActor
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_animatable_get_actor (ClutterAnimatable *animatable)
|
||||
{
|
||||
ClutterAnimatableInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL);
|
||||
|
||||
iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable);
|
||||
|
||||
g_return_val_if_fail (iface->get_actor, NULL);
|
||||
|
||||
return iface->get_actor (animatable);
|
||||
}
|
||||
|
@@ -50,6 +50,7 @@ G_DECLARE_INTERFACE (ClutterAnimatable, clutter_animatable,
|
||||
* animatable property
|
||||
* @interpolate_value: virtual function for interpolating the progress
|
||||
* of a property
|
||||
* @get_actor: virtual function for getting associated actor
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
@@ -72,6 +73,7 @@ struct _ClutterAnimatableInterface
|
||||
ClutterInterval *interval,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
ClutterActor * (* get_actor) (ClutterAnimatable *animatable);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
@@ -92,6 +94,9 @@ gboolean clutter_animatable_interpolate_value (ClutterAnimatable *animatable,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_animatable_get_actor (ClutterAnimatable *animatable);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ANIMATABLE_H__ */
|
||||
|
@@ -53,6 +53,8 @@ struct _ClutterBackend
|
||||
gfloat units_per_em;
|
||||
gint32 units_serial;
|
||||
|
||||
float fallback_resource_scale;
|
||||
|
||||
ClutterStageWindow *stage_window;
|
||||
|
||||
ClutterInputMethod *input_method;
|
||||
@@ -134,6 +136,12 @@ void clutter_set_allowed_drivers (const c
|
||||
CLUTTER_EXPORT
|
||||
ClutterStageWindow * clutter_backend_get_stage_window (ClutterBackend *backend);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
|
||||
float fallback_resource_scale);
|
||||
|
||||
float clutter_backend_get_fallback_resource_scale (ClutterBackend *backend);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_PRIVATE_H__ */
|
||||
|
@@ -601,6 +601,8 @@ clutter_backend_init (ClutterBackend *self)
|
||||
self->units_serial = 1;
|
||||
|
||||
self->dummy_onscreen = NULL;
|
||||
|
||||
self->fallback_resource_scale = 1.f;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1031,3 +1033,16 @@ clutter_backend_get_default_seat (ClutterBackend *backend)
|
||||
|
||||
return CLUTTER_BACKEND_GET_CLASS (backend)->get_default_seat (backend);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_backend_set_fallback_resource_scale (ClutterBackend *backend,
|
||||
float fallback_resource_scale)
|
||||
{
|
||||
backend->fallback_resource_scale = fallback_resource_scale;
|
||||
}
|
||||
|
||||
float
|
||||
clutter_backend_get_fallback_resource_scale (ClutterBackend *backend)
|
||||
{
|
||||
return backend->fallback_resource_scale;
|
||||
}
|
||||
|
@@ -38,12 +38,14 @@
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* // source
|
||||
* rect[0] = clutter_rectangle_new_with_color (&red_color);
|
||||
* rect[0] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[0], &red_color);
|
||||
* clutter_actor_set_position (rect[0], x_pos, y_pos);
|
||||
* clutter_actor_set_size (rect[0], 100, 100);
|
||||
*
|
||||
* // second rectangle
|
||||
* rect[1] = clutter_rectangle_new_with_color (&green_color);
|
||||
* rect[1] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[1], &green_color);
|
||||
* clutter_actor_set_size (rect[1], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[1], 0);
|
||||
*
|
||||
@@ -53,7 +55,8 @@
|
||||
* clutter_actor_add_constraint_with_name (rect[1], "green-y", constraint);
|
||||
*
|
||||
* // third rectangle
|
||||
* rect[2] = clutter_rectangle_new_with_color (&blue_color);
|
||||
* rect[2] = clutter_actor_new ();
|
||||
* clutter_actor_set_background_color (rect[2], &blue_color);
|
||||
* clutter_actor_set_size (rect[2], 100, 100);
|
||||
* clutter_actor_set_opacity (rect[2], 0);
|
||||
*
|
||||
|
@@ -167,8 +167,10 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
||||
ClutterActor *child;
|
||||
gint n_children = 0;
|
||||
gfloat minimum, natural;
|
||||
float largest_min_size, largest_nat_size;
|
||||
|
||||
minimum = natural = 0;
|
||||
largest_min_size = largest_nat_size = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter, container);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
@@ -183,8 +185,22 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
||||
get_child_size (child, priv->orientation,
|
||||
for_size, &child_min, &child_nat);
|
||||
|
||||
minimum += child_min;
|
||||
natural += child_nat;
|
||||
if (priv->is_homogeneous)
|
||||
{
|
||||
largest_min_size = MAX (largest_min_size, child_min);
|
||||
largest_nat_size = MAX (largest_nat_size, child_nat);
|
||||
}
|
||||
else
|
||||
{
|
||||
minimum += child_min;
|
||||
natural += child_nat;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->is_homogeneous)
|
||||
{
|
||||
minimum = largest_min_size * n_children;
|
||||
natural = largest_nat_size * n_children;
|
||||
}
|
||||
|
||||
if (n_children > 1)
|
||||
@@ -315,6 +331,8 @@ get_preferred_size_for_opposite_orientation (ClutterBoxLayout *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
size -= (nvis_children - 1) * priv->spacing;
|
||||
|
||||
/* Bring children up to size first */
|
||||
if (isnormal (size) || size == 0)
|
||||
{
|
||||
|
@@ -245,7 +245,13 @@ clutter_clone_allocate (ClutterActor *self,
|
||||
*/
|
||||
if (clutter_actor_get_parent (priv->clone_source) != NULL &&
|
||||
!clutter_actor_has_allocation (priv->clone_source))
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source);
|
||||
{
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
clutter_actor_get_fixed_position (priv->clone_source, &x, &y);
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source, x, y);
|
||||
}
|
||||
|
||||
clutter_actor_get_allocation_box (priv->clone_source, &source_box);
|
||||
|
||||
@@ -262,6 +268,7 @@ clutter_clone_allocate (ClutterActor *self,
|
||||
{
|
||||
priv->x_scale = x_scale;
|
||||
priv->y_scale = y_scale;
|
||||
clutter_actor_invalidate_transform (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@@ -3,13 +3,7 @@
|
||||
|
||||
#define __CLUTTER_DEPRECATED_H_INSIDE__
|
||||
|
||||
#include "deprecated/clutter-actor.h"
|
||||
#include "deprecated/clutter-box.h"
|
||||
#include "deprecated/clutter-container.h"
|
||||
#include "deprecated/clutter-group.h"
|
||||
#include "deprecated/clutter-rectangle.h"
|
||||
#include "deprecated/clutter-stage.h"
|
||||
#include "deprecated/clutter-timeline.h"
|
||||
|
||||
#undef __CLUTTER_DEPRECATED_H_INSIDE__
|
||||
|
||||
|
@@ -139,7 +139,11 @@ clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
|
||||
child != NULL;
|
||||
child = clutter_actor_get_next_sibling (child))
|
||||
{
|
||||
clutter_actor_allocate_preferred_size (child);
|
||||
float x = 0.f;
|
||||
float y = 0.f;
|
||||
|
||||
clutter_actor_get_fixed_position (child, &x, &y);
|
||||
clutter_actor_allocate_preferred_size (child, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
550
clutter/clutter/clutter-frame-clock.c
Normal file
550
clutter/clutter/clutter-frame-clock.c
Normal file
@@ -0,0 +1,550 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter/clutter-frame-clock.h"
|
||||
|
||||
#include "clutter/clutter-main.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-timeline-private.h"
|
||||
#include "cogl/cogl-trace.h"
|
||||
|
||||
enum
|
||||
{
|
||||
DESTROY,
|
||||
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS];
|
||||
|
||||
/* Wait 2ms after vblank before starting to draw next frame */
|
||||
#define SYNC_DELAY_US ms2us (2)
|
||||
|
||||
typedef struct _ClutterFrameListener
|
||||
{
|
||||
const ClutterFrameListenerIface *iface;
|
||||
gpointer user_data;
|
||||
} ClutterFrameListener;
|
||||
|
||||
typedef struct _ClutterClockSource
|
||||
{
|
||||
GSource source;
|
||||
|
||||
ClutterFrameClock *frame_clock;
|
||||
} ClutterClockSource;
|
||||
|
||||
typedef enum _ClutterFrameClockState
|
||||
{
|
||||
CLUTTER_FRAME_CLOCK_STATE_INIT,
|
||||
CLUTTER_FRAME_CLOCK_STATE_IDLE,
|
||||
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
|
||||
CLUTTER_FRAME_CLOCK_STATE_DISPATCHING,
|
||||
CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED,
|
||||
} ClutterFrameClockState;
|
||||
|
||||
struct _ClutterFrameClock
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
float refresh_rate;
|
||||
ClutterFrameListener listener;
|
||||
|
||||
GSource *source;
|
||||
|
||||
int64_t frame_count;
|
||||
|
||||
ClutterFrameClockState state;
|
||||
int64_t last_presentation_time_us;
|
||||
|
||||
gboolean is_next_presentation_time_valid;
|
||||
int64_t next_presentation_time_us;
|
||||
|
||||
gboolean pending_reschedule;
|
||||
gboolean pending_reschedule_now;
|
||||
|
||||
int inhibit_count;
|
||||
|
||||
GList *timelines;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
float
|
||||
clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
return frame_clock->refresh_rate;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
gboolean is_first;
|
||||
|
||||
if (g_list_find (frame_clock->timelines, timeline))
|
||||
return;
|
||||
|
||||
is_first = !frame_clock->timelines;
|
||||
|
||||
frame_clock->timelines = g_list_prepend (frame_clock->timelines, timeline);
|
||||
|
||||
if (is_first)
|
||||
clutter_frame_clock_schedule_update (frame_clock);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
frame_clock->timelines = g_list_remove (frame_clock->timelines, timeline);
|
||||
}
|
||||
|
||||
static void
|
||||
advance_timelines (ClutterFrameClock *frame_clock,
|
||||
int64_t time_us)
|
||||
{
|
||||
GList *timelines;
|
||||
GList *l;
|
||||
|
||||
/* we protect ourselves from timelines being removed during
|
||||
* the advancement by other timelines by copying the list of
|
||||
* timelines, taking a reference on them, iterating over the
|
||||
* copied list and then releasing the reference.
|
||||
*
|
||||
* we cannot simply take a reference on the timelines and still
|
||||
* use the list held by the master clock because the do_tick()
|
||||
* might result in the creation of a new timeline, which gets
|
||||
* added at the end of the list with no reference increase and
|
||||
* thus gets disposed at the end of the iteration.
|
||||
*
|
||||
* this implies that a newly added timeline will not be advanced
|
||||
* by this clock iteration, which is perfectly fine since we're
|
||||
* in its first cycle.
|
||||
*
|
||||
* we also cannot steal the frame clock timelines list because
|
||||
* a timeline might be removed as the direct result of do_tick()
|
||||
* and remove_timeline() would not find the timeline, failing
|
||||
* and leaving a dangling pointer behind.
|
||||
*/
|
||||
|
||||
timelines = g_list_copy (frame_clock->timelines);
|
||||
g_list_foreach (timelines, (GFunc) g_object_ref, NULL);
|
||||
|
||||
for (l = timelines; l; l = l->next)
|
||||
{
|
||||
ClutterTimeline *timeline = l->data;
|
||||
|
||||
_clutter_timeline_do_tick (timeline, time_us / 1000);
|
||||
}
|
||||
|
||||
g_list_free_full (timelines, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_reschedule_update (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
if (frame_clock->pending_reschedule ||
|
||||
frame_clock->timelines)
|
||||
{
|
||||
frame_clock->pending_reschedule = FALSE;
|
||||
|
||||
if (frame_clock->pending_reschedule_now)
|
||||
{
|
||||
frame_clock->pending_reschedule_now = FALSE;
|
||||
clutter_frame_clock_schedule_update_now (frame_clock);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_frame_clock_schedule_update (frame_clock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
ClutterFrameInfo *frame_info)
|
||||
{
|
||||
int64_t presentation_time_us = frame_info->presentation_time;
|
||||
|
||||
if (presentation_time_us > frame_clock->last_presentation_time_us ||
|
||||
((presentation_time_us - frame_clock->last_presentation_time_us) >
|
||||
INT64_MAX / 2))
|
||||
{
|
||||
frame_clock->last_presentation_time_us = presentation_time_us;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning_once ("Bogus presentation time %" G_GINT64_FORMAT
|
||||
" travelled back in time, using current time.",
|
||||
presentation_time_us);
|
||||
frame_clock->last_presentation_time_us = g_get_monotonic_time ();
|
||||
}
|
||||
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
g_warn_if_reached ();
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||
maybe_reschedule_update (frame_clock);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
||||
int64_t *out_next_update_time_us,
|
||||
int64_t *out_next_presentation_time_us)
|
||||
{
|
||||
int64_t last_presentation_time_us;
|
||||
int64_t now_us;
|
||||
float refresh_rate;
|
||||
int64_t refresh_interval_us;
|
||||
int64_t min_render_time_allowed_us;
|
||||
int64_t max_render_time_allowed_us;
|
||||
int64_t last_next_presentation_time_us;
|
||||
int64_t time_since_last_next_presentation_time_us;
|
||||
int64_t next_presentation_time_us;
|
||||
int64_t next_update_time_us;
|
||||
|
||||
now_us = g_get_monotonic_time ();
|
||||
|
||||
refresh_rate = frame_clock->refresh_rate;
|
||||
refresh_interval_us = (int64_t) (0.5 + G_USEC_PER_SEC / refresh_rate);
|
||||
|
||||
min_render_time_allowed_us = refresh_interval_us / 2;
|
||||
max_render_time_allowed_us = refresh_interval_us - SYNC_DELAY_US;
|
||||
|
||||
if (min_render_time_allowed_us > max_render_time_allowed_us)
|
||||
min_render_time_allowed_us = max_render_time_allowed_us;
|
||||
|
||||
last_presentation_time_us = frame_clock->last_presentation_time_us;
|
||||
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
|
||||
|
||||
/* Skip ahead to get close to the actual next presentation time. */
|
||||
if (next_presentation_time_us < now_us)
|
||||
{
|
||||
int64_t logical_clock_offset_us;
|
||||
int64_t logical_clock_phase_us;
|
||||
int64_t hw_clock_offset_us;
|
||||
|
||||
logical_clock_offset_us = now_us % refresh_interval_us;
|
||||
logical_clock_phase_us = now_us - logical_clock_offset_us;
|
||||
hw_clock_offset_us = last_presentation_time_us % refresh_interval_us;
|
||||
|
||||
next_presentation_time_us = logical_clock_phase_us + hw_clock_offset_us;
|
||||
}
|
||||
|
||||
/* Skip one interval if we got an early presented event. */
|
||||
last_next_presentation_time_us = frame_clock->next_presentation_time_us;
|
||||
time_since_last_next_presentation_time_us =
|
||||
next_presentation_time_us - last_next_presentation_time_us;
|
||||
if (frame_clock->is_next_presentation_time_valid &&
|
||||
time_since_last_next_presentation_time_us < (refresh_interval_us / 2))
|
||||
{
|
||||
next_presentation_time_us =
|
||||
frame_clock->next_presentation_time_us + refresh_interval_us;
|
||||
}
|
||||
|
||||
while (next_presentation_time_us < now_us + min_render_time_allowed_us)
|
||||
next_presentation_time_us += refresh_interval_us;
|
||||
|
||||
next_update_time_us = next_presentation_time_us - max_render_time_allowed_us;
|
||||
|
||||
*out_next_update_time_us = next_update_time_us;
|
||||
*out_next_presentation_time_us = next_presentation_time_us;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
frame_clock->inhibit_count++;
|
||||
|
||||
if (frame_clock->inhibit_count == 1)
|
||||
{
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
frame_clock->pending_reschedule = TRUE;
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
break;
|
||||
}
|
||||
|
||||
g_source_set_ready_time (frame_clock->source, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
g_return_if_fail (frame_clock->inhibit_count > 0);
|
||||
|
||||
frame_clock->inhibit_count--;
|
||||
|
||||
if (frame_clock->inhibit_count == 0)
|
||||
maybe_reschedule_update (frame_clock);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
int64_t next_update_time_us = -1;
|
||||
|
||||
if (frame_clock->inhibit_count > 0)
|
||||
{
|
||||
frame_clock->pending_reschedule = TRUE;
|
||||
frame_clock->pending_reschedule_now = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
next_update_time_us = g_get_monotonic_time ();
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
return;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
frame_clock->pending_reschedule = TRUE;
|
||||
frame_clock->pending_reschedule_now = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
g_warn_if_fail (next_update_time_us != -1);
|
||||
|
||||
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
||||
frame_clock->is_next_presentation_time_valid = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
int64_t next_update_time_us = -1;
|
||||
|
||||
if (frame_clock->inhibit_count > 0)
|
||||
{
|
||||
frame_clock->pending_reschedule = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
next_update_time_us = g_get_monotonic_time ();
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
calculate_next_update_time_us (frame_clock,
|
||||
&next_update_time_us,
|
||||
&frame_clock->next_presentation_time_us);
|
||||
frame_clock->is_next_presentation_time_valid = TRUE;
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
return;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
frame_clock->pending_reschedule = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
g_warn_if_fail (next_update_time_us != -1);
|
||||
|
||||
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
||||
int64_t time_us)
|
||||
{
|
||||
int64_t frame_count;
|
||||
ClutterFrameResult result;
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (ClutterFrameCLockDispatch, "Frame Clock (dispatch)");
|
||||
|
||||
g_source_set_ready_time (frame_clock->source, -1);
|
||||
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
|
||||
|
||||
frame_count = frame_clock->frame_count++;
|
||||
|
||||
COGL_TRACE_BEGIN (ClutterFrameClockEvents, "Frame Clock (before frame)");
|
||||
if (frame_clock->listener.iface->before_frame)
|
||||
{
|
||||
frame_clock->listener.iface->before_frame (frame_clock,
|
||||
frame_count,
|
||||
frame_clock->listener.user_data);
|
||||
}
|
||||
COGL_TRACE_END (ClutterFrameClockEvents);
|
||||
|
||||
COGL_TRACE_BEGIN (ClutterFrameClockTimelines, "Frame Clock (timelines)");
|
||||
advance_timelines (frame_clock, time_us);
|
||||
COGL_TRACE_END (ClutterFrameClockTimelines);
|
||||
|
||||
COGL_TRACE_BEGIN (ClutterFrameClockFrame, "Frame Clock (frame)");
|
||||
result = frame_clock->listener.iface->frame (frame_clock,
|
||||
frame_count,
|
||||
time_us,
|
||||
frame_clock->listener.user_data);
|
||||
COGL_TRACE_END (ClutterFrameClockFrame);
|
||||
|
||||
switch (frame_clock->state)
|
||||
{
|
||||
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
||||
g_warn_if_reached ();
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
||||
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
||||
break;
|
||||
case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
||||
switch (result)
|
||||
{
|
||||
case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED;
|
||||
break;
|
||||
case CLUTTER_FRAME_RESULT_IDLE:
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
||||
maybe_reschedule_update (frame_clock);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
frame_clock_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterFrameClock *frame_clock = clock_source->frame_clock;
|
||||
int64_t dispatch_time_us;
|
||||
|
||||
dispatch_time_us = g_source_get_time (source);
|
||||
clutter_frame_clock_dispatch (frame_clock, dispatch_time_us);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static GSourceFuncs frame_clock_source_funcs = {
|
||||
NULL,
|
||||
NULL,
|
||||
frame_clock_source_dispatch,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
init_frame_clock_source (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
GSource *source;
|
||||
ClutterClockSource *clock_source;
|
||||
g_autofree char *name = NULL;
|
||||
|
||||
source = g_source_new (&frame_clock_source_funcs, sizeof (ClutterClockSource));
|
||||
clock_source = (ClutterClockSource *) source;
|
||||
|
||||
name = g_strdup_printf ("Clutter frame clock (%p)", frame_clock);
|
||||
g_source_set_name (source, name);
|
||||
g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
|
||||
g_source_set_can_recurse (source, FALSE);
|
||||
clock_source->frame_clock = frame_clock;
|
||||
|
||||
frame_clock->source = source;
|
||||
g_source_attach (source, NULL);
|
||||
}
|
||||
|
||||
ClutterFrameClock *
|
||||
clutter_frame_clock_new (float refresh_rate,
|
||||
const ClutterFrameListenerIface *iface,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterFrameClock *frame_clock;
|
||||
|
||||
g_assert_cmpfloat (refresh_rate, >, 0.0);
|
||||
|
||||
frame_clock = g_object_new (CLUTTER_TYPE_FRAME_CLOCK, NULL);
|
||||
|
||||
frame_clock->listener.iface = iface;
|
||||
frame_clock->listener.user_data = user_data;
|
||||
|
||||
init_frame_clock_source (frame_clock);
|
||||
|
||||
frame_clock->refresh_rate = refresh_rate;
|
||||
|
||||
return frame_clock;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_frame_clock_destroy (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
g_object_run_dispose (G_OBJECT (frame_clock));
|
||||
g_object_unref (frame_clock);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_frame_clock_dispose (GObject *object)
|
||||
{
|
||||
ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object);
|
||||
|
||||
if (frame_clock->source)
|
||||
{
|
||||
g_signal_emit (frame_clock, signals[DESTROY], 0);
|
||||
g_source_destroy (frame_clock->source);
|
||||
g_clear_pointer (&frame_clock->source, g_source_unref);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_frame_clock_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_frame_clock_init (ClutterFrameClock *frame_clock)
|
||||
{
|
||||
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_INIT;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = clutter_frame_clock_dispose;
|
||||
|
||||
signals[DESTROY] =
|
||||
g_signal_new (I_("destroy"),
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
}
|
87
clutter/clutter/clutter-frame-clock.h
Normal file
87
clutter/clutter/clutter-frame-clock.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_FRAME_CLOCK_H
|
||||
#define CLUTTER_FRAME_CLOCK_H
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
typedef enum _ClutterFrameResult
|
||||
{
|
||||
CLUTTER_FRAME_RESULT_PENDING_PRESENTED,
|
||||
CLUTTER_FRAME_RESULT_IDLE,
|
||||
} ClutterFrameResult;
|
||||
|
||||
#define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ())
|
||||
CLUTTER_EXPORT
|
||||
G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
|
||||
CLUTTER, FRAME_CLOCK,
|
||||
GObject)
|
||||
|
||||
typedef struct _ClutterFrameListenerIface
|
||||
{
|
||||
void (* before_frame) (ClutterFrameClock *frame_clock,
|
||||
int64_t frame_count,
|
||||
gpointer user_data);
|
||||
ClutterFrameResult (* frame) (ClutterFrameClock *frame_clock,
|
||||
int64_t frame_count,
|
||||
int64_t time_us,
|
||||
gpointer user_data);
|
||||
} ClutterFrameListenerIface;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_frame_clock_new (float refresh_rate,
|
||||
const ClutterFrameListenerIface *iface,
|
||||
gpointer user_data);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_destroy (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock);
|
||||
|
||||
void clutter_frame_clock_add_timeline (ClutterFrameClock *frame_clock,
|
||||
ClutterTimeline *timeline);
|
||||
|
||||
void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
||||
ClutterTimeline *timeline);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
|
||||
|
||||
#endif /* CLUTTER_FRAME_CLOCK_H */
|
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_GROUP_H__
|
||||
#define __CLUTTER_GROUP_H__
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-actor.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_GROUP (clutter_group_get_type ())
|
||||
#define CLUTTER_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_GROUP, ClutterGroup))
|
||||
#define CLUTTER_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_GROUP, ClutterGroupClass))
|
||||
#define CLUTTER_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_GROUP))
|
||||
#define CLUTTER_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_GROUP))
|
||||
#define CLUTTER_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_GROUP, ClutterGroupClass))
|
||||
|
||||
/* XXX - ClutterGroup is to be considered fully deprecated; the only
|
||||
* reason we keep this header is because ClutterStage inherits from
|
||||
* ClutterGroup, and thus we need to have a structure definition for
|
||||
* the Stage object to expand.
|
||||
*/
|
||||
|
||||
typedef struct _ClutterGroup ClutterGroup;
|
||||
typedef struct _ClutterGroupClass ClutterGroupClass;
|
||||
typedef struct _ClutterGroupPrivate ClutterGroupPrivate;
|
||||
|
||||
/**
|
||||
* ClutterGroup:
|
||||
*
|
||||
* The #ClutterGroup structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
struct _ClutterGroup
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterGroupPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterGroupClass:
|
||||
*
|
||||
* The #ClutterGroupClass structure contains only private data
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
struct _ClutterGroupClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_clutter_reserved1) (void);
|
||||
void (*_clutter_reserved2) (void);
|
||||
void (*_clutter_reserved3) (void);
|
||||
void (*_clutter_reserved4) (void);
|
||||
void (*_clutter_reserved5) (void);
|
||||
void (*_clutter_reserved6) (void);
|
||||
};
|
||||
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_group_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_GROUP_H__ */
|
@@ -32,8 +32,7 @@
|
||||
* it has been paired, and it controls the allocation of its children.
|
||||
*
|
||||
* Any composite or container #ClutterActor subclass can delegate the
|
||||
* layouting of its children to a #ClutterLayoutManager. Clutter provides
|
||||
* a generic container using #ClutterLayoutManager called #ClutterBox.
|
||||
* layouting of its children to a #ClutterLayoutManager.
|
||||
*
|
||||
* Clutter provides some simple #ClutterLayoutManager sub-classes, like
|
||||
* #ClutterFlowLayout and #ClutterBinLayout.
|
||||
@@ -97,7 +96,7 @@
|
||||
*
|
||||
* |[
|
||||
* {
|
||||
* "type" : "ClutterBox",
|
||||
* "type" : "ClutterActor",
|
||||
* "layout-manager" : { "type" : "ClutterGridLayout" },
|
||||
* "children" : [
|
||||
* {
|
||||
|
@@ -61,7 +61,6 @@
|
||||
#include "clutter-input-pointer-a11y-private.h"
|
||||
#include "clutter-graphene.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-mutter.h"
|
||||
#include "clutter-paint-node-private.h"
|
||||
#include "clutter-private.h"
|
||||
@@ -83,10 +82,6 @@
|
||||
|
||||
/* main context */
|
||||
static ClutterMainContext *ClutterCntx = NULL;
|
||||
G_LOCK_DEFINE_STATIC (ClutterCntx);
|
||||
|
||||
/* main lock and locking/unlocking functions */
|
||||
static GMutex clutter_threads_mutex;
|
||||
|
||||
/* command line options */
|
||||
static gboolean clutter_is_initialized = FALSE;
|
||||
@@ -145,12 +140,6 @@ static const GDebugKey clutter_paint_debug_keys[] = {
|
||||
{ "damage-region", CLUTTER_DEBUG_PAINT_DAMAGE_REGION },
|
||||
};
|
||||
|
||||
static inline void
|
||||
clutter_threads_init_default (void)
|
||||
{
|
||||
g_mutex_init (&clutter_threads_mutex);
|
||||
}
|
||||
|
||||
#define ENVIRONMENT_GROUP "Environment"
|
||||
#define DEBUG_GROUP "Debug"
|
||||
|
||||
@@ -519,11 +508,7 @@ clutter_main (void)
|
||||
main_loops = g_slist_prepend (main_loops, loop);
|
||||
|
||||
if (g_main_loop_is_running (main_loops->data))
|
||||
{
|
||||
_clutter_threads_release_lock ();
|
||||
g_main_loop_run (loop);
|
||||
_clutter_threads_acquire_lock ();
|
||||
}
|
||||
g_main_loop_run (loop);
|
||||
|
||||
main_loops = g_slist_remove (main_loops, loop);
|
||||
|
||||
@@ -540,13 +525,9 @@ _clutter_threads_dispatch (gpointer data)
|
||||
ClutterThreadsDispatch *dispatch = data;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
|
||||
if (!g_source_is_destroyed (g_main_current_source ()))
|
||||
ret = dispatch->func (dispatch->data);
|
||||
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -771,40 +752,6 @@ clutter_threads_add_timeout (guint interval,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_threads_acquire_lock (void)
|
||||
{
|
||||
g_mutex_lock (&clutter_threads_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_threads_release_lock (void)
|
||||
{
|
||||
/* we need to trylock here, in case the lock hasn't been acquired; on
|
||||
* various systems trying to release a mutex that hasn't been acquired
|
||||
* will cause a run-time error. trylock() will either fail, in which
|
||||
* case we can release the lock we own; or it will succeeds, in which
|
||||
* case we need to release the lock we just acquired. so we ignore the
|
||||
* returned value.
|
||||
*
|
||||
* see: https://bugs.gnome.org/679439
|
||||
*/
|
||||
g_mutex_trylock (&clutter_threads_mutex);
|
||||
g_mutex_unlock (&clutter_threads_mutex);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_context_lock (void)
|
||||
{
|
||||
G_LOCK (ClutterCntx);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_context_unlock (void)
|
||||
{
|
||||
G_UNLOCK (ClutterCntx);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_context_is_initialized (void)
|
||||
{
|
||||
@@ -814,8 +761,8 @@ _clutter_context_is_initialized (void)
|
||||
return ClutterCntx->is_initialized;
|
||||
}
|
||||
|
||||
static ClutterMainContext *
|
||||
clutter_context_get_default_unlocked (void)
|
||||
ClutterMainContext *
|
||||
_clutter_context_get_default (void)
|
||||
{
|
||||
if (G_UNLIKELY (ClutterCntx == NULL))
|
||||
{
|
||||
@@ -846,20 +793,6 @@ clutter_context_get_default_unlocked (void)
|
||||
return ClutterCntx;
|
||||
}
|
||||
|
||||
ClutterMainContext *
|
||||
_clutter_context_get_default (void)
|
||||
{
|
||||
ClutterMainContext *retval;
|
||||
|
||||
_clutter_context_lock ();
|
||||
|
||||
retval = clutter_context_get_default_unlocked ();
|
||||
|
||||
_clutter_context_unlock ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_arg_direction_cb (const char *key,
|
||||
const char *value,
|
||||
@@ -2156,27 +2089,6 @@ _clutter_process_event (ClutterEvent *event)
|
||||
context->current_event = g_slist_delete_link (context->current_event, context->current_event);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_get_actor_by_gid:
|
||||
* @id_: a #ClutterActor unique id.
|
||||
*
|
||||
* Retrieves the #ClutterActor with @id_.
|
||||
*
|
||||
* Return value: (transfer none): the actor with the passed id or %NULL.
|
||||
* The returned actor does not have its reference count increased.
|
||||
*
|
||||
* Since: 0.6
|
||||
*
|
||||
* Deprecated: 1.8: The id is deprecated, and this function always returns
|
||||
* %NULL. Use the proper scene graph API in #ClutterActor to find a child
|
||||
* of the stage.
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_get_actor_by_gid (guint32 id_)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_base_init (void)
|
||||
{
|
||||
@@ -2191,9 +2103,6 @@ clutter_base_init (void)
|
||||
g_type_init ();
|
||||
#endif
|
||||
|
||||
/* initialise the Big Clutter Lock™ if necessary */
|
||||
clutter_threads_init_default ();
|
||||
|
||||
clutter_graphene_init ();
|
||||
}
|
||||
}
|
||||
@@ -2261,9 +2170,7 @@ clutter_threads_remove_repaint_func (guint handle_id)
|
||||
|
||||
g_return_if_fail (handle_id > 0);
|
||||
|
||||
_clutter_context_lock ();
|
||||
|
||||
context = clutter_context_get_default_unlocked ();
|
||||
context = _clutter_context_get_default ();
|
||||
l = context->repaint_funcs;
|
||||
while (l != NULL)
|
||||
{
|
||||
@@ -2286,8 +2193,6 @@ clutter_threads_remove_repaint_func (guint handle_id)
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
_clutter_context_unlock ();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2386,9 +2291,7 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
|
||||
|
||||
g_return_val_if_fail (func != NULL, 0);
|
||||
|
||||
_clutter_context_lock ();
|
||||
|
||||
context = clutter_context_get_default_unlocked ();
|
||||
context = _clutter_context_get_default ();
|
||||
|
||||
repaint_func = g_slice_new (ClutterRepaintFunction);
|
||||
|
||||
@@ -2402,8 +2305,6 @@ clutter_threads_add_repaint_func_full (ClutterRepaintFlags flags,
|
||||
context->repaint_funcs = g_list_prepend (context->repaint_funcs,
|
||||
repaint_func);
|
||||
|
||||
_clutter_context_unlock ();
|
||||
|
||||
return repaint_func->id;
|
||||
}
|
||||
|
||||
|
@@ -1,618 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SECTION:clutter-master-clock-default
|
||||
* @short_description: The default master clock for all animations
|
||||
*
|
||||
* The #ClutterMasterClockDefault class is the default implementation
|
||||
* of #ClutterMasterClock.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-master-clock-default.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-manager-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
#define clutter_warn_if_over_budget(master_clock,start_time,section) G_STMT_START { \
|
||||
gint64 __delta = g_get_monotonic_time () - start_time; \
|
||||
gint64 __budget = master_clock->remaining_budget; \
|
||||
if (__budget > 0 && __delta >= __budget) { \
|
||||
_clutter_diagnostic_message ("%s took %" G_GINT64_FORMAT " microseconds " \
|
||||
"more than the remaining budget of %" G_GINT64_FORMAT \
|
||||
" microseconds", \
|
||||
section, __delta - __budget, __budget); \
|
||||
} } G_STMT_END
|
||||
#else
|
||||
#define clutter_warn_if_over_budget(master_clock,start_time,section)
|
||||
#endif
|
||||
|
||||
typedef struct _ClutterClockSource ClutterClockSource;
|
||||
|
||||
struct _ClutterMasterClockDefault
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
/* the list of timelines handled by the clock */
|
||||
GSList *timelines;
|
||||
|
||||
/* the current state of the clock, in usecs */
|
||||
gint64 cur_tick;
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
gint64 frame_budget;
|
||||
gint64 remaining_budget;
|
||||
#endif
|
||||
|
||||
/* an idle source, used by the Master Clock to queue
|
||||
* a redraw on the stage and drive the animations
|
||||
*/
|
||||
GSource *source;
|
||||
|
||||
guint ensure_next_iteration : 1;
|
||||
|
||||
guint paused : 1;
|
||||
};
|
||||
|
||||
struct _ClutterClockSource
|
||||
{
|
||||
GSource source;
|
||||
|
||||
ClutterMasterClockDefault *master_clock;
|
||||
};
|
||||
|
||||
static gboolean clutter_clock_prepare (GSource *source,
|
||||
gint *timeout);
|
||||
static gboolean clutter_clock_check (GSource *source);
|
||||
static gboolean clutter_clock_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data);
|
||||
|
||||
static GSourceFuncs clock_funcs = {
|
||||
clutter_clock_prepare,
|
||||
clutter_clock_check,
|
||||
clutter_clock_dispatch,
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
clutter_master_clock_iface_init (ClutterMasterClockInterface *iface);
|
||||
|
||||
#define clutter_master_clock_default_get_type _clutter_master_clock_default_get_type
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterMasterClockDefault,
|
||||
clutter_master_clock_default,
|
||||
G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_MASTER_CLOCK,
|
||||
clutter_master_clock_iface_init));
|
||||
|
||||
/*
|
||||
* master_clock_is_running:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
*
|
||||
* Checks if we should currently be advancing timelines or redrawing
|
||||
* stages.
|
||||
*
|
||||
* Return value: %TRUE if the #ClutterMasterClock has at least
|
||||
* one running timeline
|
||||
*/
|
||||
static gboolean
|
||||
master_clock_is_running (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
const GSList *stages, *l;
|
||||
|
||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
if (master_clock->paused)
|
||||
return FALSE;
|
||||
|
||||
if (master_clock->timelines)
|
||||
return TRUE;
|
||||
|
||||
for (l = stages; l; l = l->next)
|
||||
{
|
||||
if (clutter_actor_is_mapped (l->data) &&
|
||||
(_clutter_stage_has_queued_events (l->data) ||
|
||||
_clutter_stage_needs_update (l->data)))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (master_clock->ensure_next_iteration)
|
||||
{
|
||||
master_clock->ensure_next_iteration = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gint
|
||||
master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
const GSList *stages, *l;
|
||||
gint64 min_update_time = -1;
|
||||
|
||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
{
|
||||
gint64 update_time = _clutter_stage_get_update_time (l->data);
|
||||
if (min_update_time == -1 ||
|
||||
(update_time != -1 && update_time < min_update_time))
|
||||
min_update_time = update_time;
|
||||
}
|
||||
|
||||
if (min_update_time == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gint64 now = g_source_get_time (master_clock->source);
|
||||
if (min_update_time < now)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
gint64 delay_us = min_update_time - now;
|
||||
return (delay_us + 999) / 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
const GSList *stages, *l;
|
||||
|
||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
clutter_stage_schedule_update (l->data);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
master_clock_list_ready_stages (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
const GSList *stages, *l;
|
||||
GSList *result;
|
||||
|
||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
result = NULL;
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
{
|
||||
gint64 update_time = _clutter_stage_get_update_time (l->data);
|
||||
/* We carefully avoid to update stages that aren't mapped, because
|
||||
* they have nothing to render and this could cause a deadlock with
|
||||
* some of the SwapBuffers implementations (in particular
|
||||
* GLX_INTEL_swap_event is not emitted if nothing was rendered).
|
||||
*
|
||||
* Also, if a stage has a swap-buffers pending we don't want to draw
|
||||
* to it in case the driver may block the CPU while it waits for the
|
||||
* next backbuffer to become available.
|
||||
*
|
||||
* TODO: We should be able to identify if we are running triple or N
|
||||
* buffered and in these cases we can still draw if there is 1 swap
|
||||
* pending so we can hopefully always be ready to swap for the next
|
||||
* vblank and really match the vsync frequency.
|
||||
*/
|
||||
if (clutter_actor_is_mapped (l->data) &&
|
||||
update_time != -1 && update_time <= master_clock->cur_tick)
|
||||
result = g_slist_prepend (result, g_object_ref (l->data));
|
||||
}
|
||||
|
||||
return g_slist_reverse (result);
|
||||
}
|
||||
|
||||
static void
|
||||
master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
|
||||
GSList *stages)
|
||||
{
|
||||
const GSList *l;
|
||||
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
{
|
||||
/* Clear the old update time */
|
||||
_clutter_stage_clear_update_time (l->data);
|
||||
|
||||
/* And if there is still work to be done, schedule a new one */
|
||||
if (master_clock->timelines ||
|
||||
_clutter_stage_has_queued_events (l->data) ||
|
||||
_clutter_stage_needs_update (l->data))
|
||||
clutter_stage_schedule_update (l->data);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* master_clock_next_frame_delay:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
*
|
||||
* Computes the number of delay before we need to draw the next frame.
|
||||
*
|
||||
* Return value: -1 if there is no next frame pending, otherwise the
|
||||
* number of millseconds before the we need to draw the next frame
|
||||
*/
|
||||
static gint
|
||||
master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
if (!master_clock_is_running (master_clock))
|
||||
return -1;
|
||||
|
||||
/* If all of the stages are busy waiting for a swap-buffers to complete
|
||||
* then we wait for one to be ready.. */
|
||||
return master_clock_get_swap_wait_time (master_clock);
|
||||
}
|
||||
|
||||
static void
|
||||
master_clock_process_events (ClutterMasterClockDefault *master_clock,
|
||||
GSList *stages)
|
||||
{
|
||||
GSList *l;
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
gint64 start = g_get_monotonic_time ();
|
||||
#endif
|
||||
|
||||
/* Process queued events */
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
_clutter_stage_process_queued_events (l->data);
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
if (_clutter_diagnostic_enabled ())
|
||||
clutter_warn_if_over_budget (master_clock, start, "Event processing");
|
||||
|
||||
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* master_clock_advance_timelines:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
*
|
||||
* Advances all the timelines held by the master clock. This function
|
||||
* should be called before calling _clutter_stage_do_update() to
|
||||
* make sure that all the timelines are advanced and the scene is updated.
|
||||
*/
|
||||
static void
|
||||
master_clock_advance_timelines (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
GSList *timelines, *l;
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
gint64 start = g_get_monotonic_time ();
|
||||
#endif
|
||||
|
||||
/* we protect ourselves from timelines being removed during
|
||||
* the advancement by other timelines by copying the list of
|
||||
* timelines, taking a reference on them, iterating over the
|
||||
* copied list and then releasing the reference.
|
||||
*
|
||||
* we cannot simply take a reference on the timelines and still
|
||||
* use the list held by the master clock because the do_tick()
|
||||
* might result in the creation of a new timeline, which gets
|
||||
* added at the end of the list with no reference increase and
|
||||
* thus gets disposed at the end of the iteration.
|
||||
*
|
||||
* this implies that a newly added timeline will not be advanced
|
||||
* by this clock iteration, which is perfectly fine since we're
|
||||
* in its first cycle.
|
||||
*
|
||||
* we also cannot steal the master clock timelines list because
|
||||
* a timeline might be removed as the direct result of do_tick()
|
||||
* and remove_timeline() would not find the timeline, failing
|
||||
* and leaving a dangling pointer behind.
|
||||
*/
|
||||
timelines = g_slist_copy (master_clock->timelines);
|
||||
g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);
|
||||
|
||||
for (l = timelines; l != NULL; l = l->next)
|
||||
_clutter_timeline_do_tick (l->data, master_clock->cur_tick / 1000);
|
||||
|
||||
g_slist_free_full (timelines, g_object_unref);
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
if (_clutter_diagnostic_enabled ())
|
||||
clutter_warn_if_over_budget (master_clock, start, "Animations");
|
||||
|
||||
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
master_clock_update_stages (ClutterMasterClockDefault *master_clock,
|
||||
GSList *stages)
|
||||
{
|
||||
gboolean stages_updated = FALSE;
|
||||
GSList *l;
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
gint64 start = g_get_monotonic_time ();
|
||||
#endif
|
||||
|
||||
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT);
|
||||
|
||||
/* Update any stage that needs redraw/relayout after the clock
|
||||
* is advanced.
|
||||
*/
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
stages_updated |= _clutter_stage_do_update (l->data);
|
||||
|
||||
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
if (_clutter_diagnostic_enabled ())
|
||||
clutter_warn_if_over_budget (master_clock, start, "Updating the stage");
|
||||
|
||||
master_clock->remaining_budget -= (g_get_monotonic_time () - start);
|
||||
#endif
|
||||
|
||||
return stages_updated;
|
||||
}
|
||||
|
||||
/*
|
||||
* clutter_clock_source_new:
|
||||
* @master_clock: a #ClutterMasterClock for the source
|
||||
*
|
||||
* The #ClutterClockSource is an idle GSource that will queue a redraw
|
||||
* if @master_clock has at least a running #ClutterTimeline. The redraw
|
||||
* will cause @master_clock to advance all timelines, thus advancing all
|
||||
* animations as well.
|
||||
*
|
||||
* Return value: the newly created #GSource
|
||||
*/
|
||||
static GSource *
|
||||
clutter_clock_source_new (ClutterMasterClockDefault *master_clock)
|
||||
{
|
||||
GSource *source = g_source_new (&clock_funcs, sizeof (ClutterClockSource));
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
|
||||
g_source_set_name (source, "Clutter master clock");
|
||||
g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
|
||||
g_source_set_can_recurse (source, FALSE);
|
||||
clock_source->master_clock = master_clock;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clock_prepare (GSource *source,
|
||||
gint *timeout)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
|
||||
int delay;
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags &
|
||||
CLUTTER_DEBUG_CONTINUOUS_REDRAW))
|
||||
{
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
const GSList *stages, *l;
|
||||
|
||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
/* Queue a full redraw on all of the stages */
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
clutter_actor_queue_redraw (l->data);
|
||||
}
|
||||
|
||||
delay = master_clock_next_frame_delay (master_clock);
|
||||
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
*timeout = delay;
|
||||
|
||||
return delay == 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clock_check (GSource *source)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
|
||||
int delay;
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
delay = master_clock_next_frame_delay (master_clock);
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
return delay == 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clock_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterMasterClockDefault *master_clock = clock_source->master_clock;
|
||||
GSList *stages;
|
||||
|
||||
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
|
||||
COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)");
|
||||
|
||||
/* Get the time to use for this frame */
|
||||
master_clock->cur_tick = g_source_get_time (source);
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
master_clock->remaining_budget = master_clock->frame_budget;
|
||||
#endif
|
||||
|
||||
/* We need to protect ourselves against stages being destroyed during
|
||||
* event handling - master_clock_list_ready_stages() returns a
|
||||
* list of referenced that we'll unref afterwards.
|
||||
*/
|
||||
stages = master_clock_list_ready_stages (master_clock);
|
||||
|
||||
/* Each frame is split into three separate phases: */
|
||||
|
||||
/* 1. process all the events; each stage goes through its events queue
|
||||
* and processes each event according to its type, then emits the
|
||||
* various signals that are associated with the event
|
||||
*/
|
||||
master_clock_process_events (master_clock, stages);
|
||||
|
||||
/* 2. advance the timelines */
|
||||
master_clock_advance_timelines (master_clock);
|
||||
|
||||
/* 3. relayout and redraw the stages */
|
||||
master_clock_update_stages (master_clock, stages);
|
||||
|
||||
master_clock_reschedule_stage_updates (master_clock, stages);
|
||||
|
||||
g_slist_free_full (stages, g_object_unref);
|
||||
|
||||
COGL_TRACE_END (ClutterMasterClockTick);
|
||||
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterMasterClockDefault *master_clock = CLUTTER_MASTER_CLOCK_DEFAULT (gobject);
|
||||
|
||||
g_slist_free (master_clock->timelines);
|
||||
|
||||
G_OBJECT_CLASS (clutter_master_clock_default_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_class_init (ClutterMasterClockDefaultClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = clutter_master_clock_default_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_init (ClutterMasterClockDefault *self)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
source = clutter_clock_source_new (self);
|
||||
self->source = source;
|
||||
|
||||
self->ensure_next_iteration = FALSE;
|
||||
self->paused = FALSE;
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
self->frame_budget = G_USEC_PER_SEC / 60;
|
||||
#endif
|
||||
|
||||
g_source_attach (source, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_add_timeline (ClutterMasterClock *clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
|
||||
gboolean is_first;
|
||||
|
||||
if (g_slist_find (master_clock->timelines, timeline))
|
||||
return;
|
||||
|
||||
is_first = master_clock->timelines == NULL;
|
||||
|
||||
master_clock->timelines = g_slist_prepend (master_clock->timelines,
|
||||
timeline);
|
||||
|
||||
if (is_first)
|
||||
{
|
||||
master_clock_schedule_stage_updates (master_clock);
|
||||
_clutter_master_clock_start_running (clock);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_remove_timeline (ClutterMasterClock *clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
|
||||
|
||||
master_clock->timelines = g_slist_remove (master_clock->timelines,
|
||||
timeline);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_start_running (ClutterMasterClock *master_clock)
|
||||
{
|
||||
/* If called from a different thread, we need to wake up the
|
||||
* main loop to start running the timelines
|
||||
*/
|
||||
g_main_context_wakeup (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_ensure_next_iteration (ClutterMasterClock *clock)
|
||||
{
|
||||
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
|
||||
|
||||
master_clock->ensure_next_iteration = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_set_paused (ClutterMasterClock *clock,
|
||||
gboolean paused)
|
||||
{
|
||||
ClutterMasterClockDefault *master_clock = (ClutterMasterClockDefault *) clock;
|
||||
|
||||
if (paused && !master_clock->paused)
|
||||
{
|
||||
g_clear_pointer (&master_clock->source, g_source_destroy);
|
||||
}
|
||||
else if (!paused && master_clock->paused)
|
||||
{
|
||||
master_clock->source = clutter_clock_source_new (master_clock);
|
||||
g_source_attach (master_clock->source, NULL);
|
||||
}
|
||||
|
||||
master_clock->paused = !!paused;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_iface_init (ClutterMasterClockInterface *iface)
|
||||
{
|
||||
iface->add_timeline = clutter_master_clock_default_add_timeline;
|
||||
iface->remove_timeline = clutter_master_clock_default_remove_timeline;
|
||||
iface->start_running = clutter_master_clock_default_start_running;
|
||||
iface->ensure_next_iteration = clutter_master_clock_default_ensure_next_iteration;
|
||||
iface->set_paused = clutter_master_clock_default_set_paused;
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Lionel Landwerlin <lionel.g.landwerlin@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2015 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_MASTER_CLOCK_DEFAULT_H__
|
||||
#define __CLUTTER_MASTER_CLOCK_DEFAULT_H__
|
||||
|
||||
#include <clutter/clutter-timeline.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_MASTER_CLOCK_DEFAULT (_clutter_master_clock_default_get_type ())
|
||||
#define CLUTTER_MASTER_CLOCK_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefault))
|
||||
#define CLUTTER_IS_MASTER_CLOCK_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT))
|
||||
#define CLUTTER_MASTER_CLOCK_DEFAULT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, ClutterMasterClockDefaultClass))
|
||||
|
||||
typedef struct _ClutterMasterClockDefault ClutterMasterClockDefault;
|
||||
typedef struct _ClutterMasterClockDefaultClass ClutterMasterClockDefaultClass;
|
||||
|
||||
struct _ClutterMasterClockDefaultClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
GType _clutter_master_clock_default_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_MASTER_CLOCK_DEFAULT_H__ */
|
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SECTION:clutter-master-clock
|
||||
* @short_description: The master clock for all animations
|
||||
*
|
||||
* The #ClutterMasterClock class is responsible for advancing all
|
||||
* #ClutterTimelines when a stage is being redrawn. The master clock
|
||||
* makes sure that the scenegraph is always integrally updated before
|
||||
* painting it.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-master-clock-default.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
G_DEFINE_INTERFACE (ClutterMasterClock, clutter_master_clock, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
clutter_master_clock_default_init (ClutterMasterClockInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterMasterClock *
|
||||
_clutter_master_clock_get_default (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
|
||||
if (G_UNLIKELY (context->master_clock == NULL))
|
||||
context->master_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK_DEFAULT, NULL);
|
||||
|
||||
return context->master_clock;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_add_timeline:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
* @timeline: a #ClutterTimeline
|
||||
*
|
||||
* Adds @timeline to the list of playing timelines held by the master
|
||||
* clock.
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->add_timeline (master_clock,
|
||||
timeline);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_remove_timeline:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
* @timeline: a #ClutterTimeline
|
||||
*
|
||||
* Removes @timeline from the list of playing timelines held by the
|
||||
* master clock.
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->remove_timeline (master_clock,
|
||||
timeline);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_start_running:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
*
|
||||
* Called when we have events or redraws to process; if the clock
|
||||
* is stopped, does the processing necessary to wake it up again.
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_start_running (ClutterMasterClock *master_clock)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->start_running (master_clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* _clutter_master_clock_ensure_next_iteration:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
*
|
||||
* Ensures that the master clock will run at least one iteration
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->ensure_next_iteration (master_clock);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_master_clock_set_paused (ClutterMasterClock *master_clock,
|
||||
gboolean paused)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
CLUTTER_MASTER_CLOCK_GET_IFACE (master_clock)->set_paused (master_clock,
|
||||
!!paused);
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_MASTER_CLOCK_H__
|
||||
#define __CLUTTER_MASTER_CLOCK_H__
|
||||
|
||||
#include <clutter/clutter-timeline.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_MASTER_CLOCK (clutter_master_clock_get_type ())
|
||||
G_DECLARE_INTERFACE (ClutterMasterClock, clutter_master_clock,
|
||||
CLUTTER, MASTER_CLOCK,
|
||||
GObject)
|
||||
|
||||
struct _ClutterMasterClockInterface
|
||||
{
|
||||
/*< private >*/
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
void (* add_timeline) (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline);
|
||||
void (* remove_timeline) (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline);
|
||||
void (* start_running) (ClutterMasterClock *master_clock);
|
||||
void (* ensure_next_iteration) (ClutterMasterClock *master_clock);
|
||||
void (* set_paused) (ClutterMasterClock *master_clock,
|
||||
gboolean paused);
|
||||
};
|
||||
|
||||
ClutterMasterClock * _clutter_master_clock_get_default (void);
|
||||
void _clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline);
|
||||
void _clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline);
|
||||
void _clutter_master_clock_start_running (ClutterMasterClock *master_clock);
|
||||
void _clutter_master_clock_ensure_next_iteration (ClutterMasterClock *master_clock);
|
||||
void _clutter_master_clock_set_paused (ClutterMasterClock *master_clock,
|
||||
gboolean paused);
|
||||
|
||||
void _clutter_timeline_advance (ClutterTimeline *timeline,
|
||||
gint64 tick_time);
|
||||
gint64 _clutter_timeline_get_delta (ClutterTimeline *timeline);
|
||||
void _clutter_timeline_do_tick (ClutterTimeline *timeline,
|
||||
gint64 tick_time);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_MASTER_CLOCK_H__ */
|
@@ -39,6 +39,10 @@
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_stage_peek_stage_views (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_actor_is_effectively_on_stage_view (ClutterActor *self,
|
||||
ClutterStageView *view);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_set_custom_backend_func (ClutterBackend *(* func) (void));
|
||||
|
||||
@@ -68,12 +72,6 @@ gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
|
||||
ClutterPaintFlag paint_flags,
|
||||
GError **error);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_freeze_updates (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_thaw_updates (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_clear_stage_views (ClutterStage *stage);
|
||||
|
||||
|
@@ -238,8 +238,8 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
gfloat stage_width, stage_height;
|
||||
gfloat target_width = -1, target_height = -1;
|
||||
CoglFramebuffer *framebuffer;
|
||||
gfloat resource_scale;
|
||||
gfloat ceiled_resource_scale;
|
||||
float resource_scale;
|
||||
float ceiled_resource_scale;
|
||||
graphene_point3d_t local_offset;
|
||||
gfloat old_viewport[4];
|
||||
|
||||
@@ -254,17 +254,11 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect,
|
||||
stage = _clutter_actor_get_stage_internal (priv->actor);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
|
||||
if (_clutter_actor_get_real_resource_scale (priv->actor, &resource_scale))
|
||||
{
|
||||
ceiled_resource_scale = ceilf (resource_scale);
|
||||
stage_width *= ceiled_resource_scale;
|
||||
stage_height *= ceiled_resource_scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are sure we have a resource scale set to a good value at paint */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
resource_scale = clutter_actor_get_real_resource_scale (priv->actor);
|
||||
|
||||
ceiled_resource_scale = ceilf (resource_scale);
|
||||
stage_width *= ceiled_resource_scale;
|
||||
stage_height *= ceiled_resource_scale;
|
||||
|
||||
/* Get the minimal bounding box for what we want to paint, relative to the
|
||||
* parent of priv->actor. Note that we may actually be painting a clone of
|
||||
@@ -417,8 +411,9 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect,
|
||||
*/
|
||||
cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
|
||||
|
||||
if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) &&
|
||||
resource_scale != 1.0f)
|
||||
resource_scale = clutter_actor_get_resource_scale (priv->actor);
|
||||
|
||||
if (resource_scale != 1.0f)
|
||||
{
|
||||
float paint_scale = 1.0f / resource_scale;
|
||||
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
|
||||
|
@@ -1412,6 +1412,7 @@ clutter_layer_node_new (const CoglMatrix *projection,
|
||||
{
|
||||
ClutterLayerNode *res;
|
||||
CoglContext *context;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglTexture *texture;
|
||||
CoglColor color;
|
||||
|
||||
@@ -1426,9 +1427,10 @@ clutter_layer_node_new (const CoglMatrix *projection,
|
||||
/* the texture backing the FBO */
|
||||
context = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
|
||||
texture = cogl_texture_2d_new_with_size (context,
|
||||
MAX (res->fbo_width, 1),
|
||||
MAX (res->fbo_height, 1));
|
||||
tex_2d = cogl_texture_2d_new_with_size (context,
|
||||
MAX (res->fbo_width, 1),
|
||||
MAX (res->fbo_height, 1));
|
||||
texture = COGL_TEXTURE (tex_2d);
|
||||
cogl_texture_set_premultiplied (texture, TRUE);
|
||||
|
||||
res->offscreen = COGL_FRAMEBUFFER (cogl_offscreen_new_to_texture (texture));
|
||||
|
@@ -62,6 +62,7 @@
|
||||
#include "clutter-gesture-action-private.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-timeline.h"
|
||||
#include <math.h>
|
||||
|
||||
#define FLOAT_EPSILON (1e-15)
|
||||
@@ -326,8 +327,12 @@ gesture_end (ClutterGestureAction *gesture,
|
||||
if (ABS (velocity) * priv->acceleration_factor > min_velocity &&
|
||||
duration > FLOAT_EPSILON)
|
||||
{
|
||||
ClutterActor *pan_actor =
|
||||
clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gesture));
|
||||
|
||||
priv->interpolated_x = priv->interpolated_y = 0.0f;
|
||||
priv->deceleration_timeline = clutter_timeline_new (duration);
|
||||
priv->deceleration_timeline = clutter_timeline_new_for_actor (pan_actor,
|
||||
duration);
|
||||
clutter_timeline_set_progress_mode (priv->deceleration_timeline,
|
||||
CLUTTER_EASE_OUT_EXPO);
|
||||
|
||||
@@ -458,6 +463,8 @@ clutter_pan_action_set_actor (ClutterActorMeta *meta,
|
||||
/* make sure we reset the state */
|
||||
if (priv->state == PAN_STATE_INTERPOLATING)
|
||||
g_clear_object (&priv->deceleration_timeline);
|
||||
else if (priv->deceleration_timeline)
|
||||
clutter_timeline_set_actor (priv->deceleration_timeline, actor);
|
||||
}
|
||||
|
||||
CLUTTER_ACTOR_META_CLASS (clutter_pan_action_parent_class)->set_actor (meta,
|
||||
|
@@ -37,7 +37,6 @@
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-id-pool.h"
|
||||
#include "clutter-layout-manager.h"
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-settings.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-stage.h"
|
||||
@@ -122,9 +121,6 @@ struct _ClutterMainContext
|
||||
/* the object holding all the stage instances */
|
||||
ClutterStageManager *stage_manager;
|
||||
|
||||
/* the clock driving all the frame operations */
|
||||
ClutterMasterClock *master_clock;
|
||||
|
||||
/* the main event queue */
|
||||
GQueue *events_queue;
|
||||
|
||||
@@ -177,11 +173,6 @@ typedef struct
|
||||
gboolean _clutter_threads_dispatch (gpointer data);
|
||||
void _clutter_threads_dispatch_free (gpointer data);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_threads_acquire_lock (void);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_threads_release_lock (void);
|
||||
|
||||
ClutterMainContext * _clutter_context_get_default (void);
|
||||
void _clutter_context_lock (void);
|
||||
void _clutter_context_unlock (void);
|
||||
@@ -316,6 +307,30 @@ gboolean _clutter_run_progress_function (GType gtype,
|
||||
|
||||
void clutter_timeline_cancel_delay (ClutterTimeline *timeline);
|
||||
|
||||
static inline uint64_t
|
||||
us (uint64_t us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ms2us (uint64_t ms)
|
||||
{
|
||||
return us (ms * 1000);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
us2ms (uint64_t us)
|
||||
{
|
||||
return (uint32_t) (us / 1000);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ns2us (uint64_t ns)
|
||||
{
|
||||
return us (ns / 1000);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_PRIVATE_H__ */
|
||||
|
@@ -278,6 +278,26 @@ clutter_property_transition_init (ClutterPropertyTransition *self)
|
||||
self->priv = clutter_property_transition_get_instance_private (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_property_transition_new_for_actor:
|
||||
* @actor: a #ClutterActor
|
||||
* @property_name: (allow-none): a property of @animatable, or %NULL
|
||||
*
|
||||
* Creates a new #ClutterPropertyTransition.
|
||||
*
|
||||
* Return value: (transfer full): the newly created #ClutterPropertyTransition.
|
||||
* Use g_object_unref() when done
|
||||
*/
|
||||
ClutterTransition *
|
||||
clutter_property_transition_new_for_actor (ClutterActor *actor,
|
||||
const char *property_name)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_PROPERTY_TRANSITION,
|
||||
"actor", actor,
|
||||
"property-name", property_name,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_property_transition_new:
|
||||
* @property_name: (allow-none): a property of @animatable, or %NULL
|
||||
|
@@ -78,8 +78,13 @@ struct _ClutterPropertyTransitionClass
|
||||
CLUTTER_EXPORT
|
||||
GType clutter_property_transition_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterTransition * clutter_property_transition_new_for_actor (ClutterActor *actor,
|
||||
const char *property_name);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterTransition * clutter_property_transition_new (const char *property_name);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_property_transition_set_property_name (ClutterPropertyTransition *transition,
|
||||
const char *property_name);
|
||||
|
@@ -50,14 +50,14 @@
|
||||
* <informalexample><programlisting><![CDATA[
|
||||
* {
|
||||
* "id" : "red-button",
|
||||
* "type" : "ClutterRectangle",
|
||||
* "type" : "ClutterActor",
|
||||
* "width" : 100,
|
||||
* "height" : 100,
|
||||
* "color" : "#ff0000ff"
|
||||
* "background-color" : "#ff0000ff"
|
||||
* }
|
||||
* ]]></programlisting></informalexample>
|
||||
*
|
||||
* This will produce a red #ClutterRectangle, 100x100 pixels wide, and
|
||||
* This will produce a red #ClutterActor, 100x100 pixels wide, and
|
||||
* with a ClutterScript id of "red-button"; it can be retrieved by calling:
|
||||
*
|
||||
* |[
|
||||
|
@@ -40,7 +40,14 @@ void clutter_stage_paint_view (ClutterStage
|
||||
ClutterStageView *view,
|
||||
const cairo_region_t *redraw_clip);
|
||||
|
||||
void _clutter_stage_emit_after_paint (ClutterStage *stage);
|
||||
void clutter_stage_emit_before_update (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
void clutter_stage_emit_before_paint (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
void clutter_stage_emit_after_paint (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
void clutter_stage_emit_after_update (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_stage_set_window (ClutterStage *stage,
|
||||
@@ -58,9 +65,12 @@ void _clutter_stage_get_viewport (ClutterStage
|
||||
void _clutter_stage_dirty_viewport (ClutterStage *stage);
|
||||
void _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
void _clutter_stage_maybe_relayout (ClutterActor *stage);
|
||||
gboolean _clutter_stage_needs_update (ClutterStage *stage);
|
||||
gboolean _clutter_stage_do_update (ClutterStage *stage);
|
||||
void clutter_stage_maybe_relayout (ClutterActor *stage);
|
||||
void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
|
||||
GSList * clutter_stage_find_updated_devices (ClutterStage *stage);
|
||||
void clutter_stage_update_devices (ClutterStage *stage,
|
||||
GSList *devices);
|
||||
void clutter_stage_update_actor_stage_views (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_stage_queue_event (ClutterStage *stage,
|
||||
@@ -69,8 +79,6 @@ void _clutter_stage_queue_event (ClutterStage *stage,
|
||||
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
||||
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
||||
void _clutter_stage_update_input_devices (ClutterStage *stage);
|
||||
gint64 _clutter_stage_get_update_time (ClutterStage *stage);
|
||||
void _clutter_stage_clear_update_time (ClutterStage *stage);
|
||||
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
|
||||
|
||||
void clutter_stage_log_pick (ClutterStage *stage,
|
||||
@@ -126,16 +134,21 @@ gboolean _clutter_stage_update_state (ClutterStage *stag
|
||||
void _clutter_stage_set_scale_factor (ClutterStage *stage,
|
||||
int factor);
|
||||
|
||||
void _clutter_stage_presented (ClutterStage *stage,
|
||||
CoglFrameEvent frame_event,
|
||||
void clutter_stage_presented (ClutterStage *stage,
|
||||
ClutterStageView *view,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
|
||||
ClutterActor *actor);
|
||||
|
||||
void clutter_stage_dequeue_actor_relayout (ClutterStage *stage,
|
||||
ClutterActor *actor);
|
||||
|
||||
GList * clutter_stage_get_views_for_rect (ClutterStage *stage,
|
||||
const graphene_rect_t *rect);
|
||||
|
||||
void clutter_stage_set_actor_needs_immediate_relayout (ClutterStage *stage);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#define __CLUTTER_STAGE_VIEW_PRIVATE_H__
|
||||
|
||||
#include "clutter/clutter-stage-view.h"
|
||||
#include "clutter/clutter-types.h"
|
||||
|
||||
void clutter_stage_view_after_paint (ClutterStageView *view,
|
||||
cairo_region_t *redraw_clip);
|
||||
@@ -62,4 +63,12 @@ void clutter_stage_view_transform_rect_to_onscreen (ClutterStageView
|
||||
int dst_height,
|
||||
cairo_rectangle_int_t *dst_rect);
|
||||
|
||||
void clutter_stage_view_schedule_update (ClutterStageView *view);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
float clutter_stage_view_get_refresh_rate (ClutterStageView *view);
|
||||
|
||||
void clutter_stage_view_notify_presented (ClutterStageView *view,
|
||||
ClutterFrameInfo *frame_info);
|
||||
|
||||
#endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
|
||||
|
@@ -24,8 +24,10 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter/clutter-damage-history.h"
|
||||
#include "clutter/clutter-frame-clock.h"
|
||||
#include "clutter/clutter-private.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "clutter/clutter-stage-private.h"
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
enum
|
||||
@@ -33,11 +35,13 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_NAME,
|
||||
PROP_STAGE,
|
||||
PROP_LAYOUT,
|
||||
PROP_FRAMEBUFFER,
|
||||
PROP_OFFSCREEN,
|
||||
PROP_USE_SHADOWFB,
|
||||
PROP_SCALE,
|
||||
PROP_REFRESH_RATE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@@ -48,6 +52,8 @@ typedef struct _ClutterStageViewPrivate
|
||||
{
|
||||
char *name;
|
||||
|
||||
ClutterStage *stage;
|
||||
|
||||
cairo_rectangle_int_t layout;
|
||||
float scale;
|
||||
CoglFramebuffer *framebuffer;
|
||||
@@ -71,6 +77,9 @@ typedef struct _ClutterStageViewPrivate
|
||||
gboolean has_redraw_clip;
|
||||
cairo_region_t *redraw_clip;
|
||||
|
||||
float refresh_rate;
|
||||
ClutterFrameClock *frame_clock;
|
||||
|
||||
guint dirty_viewport : 1;
|
||||
guint dirty_projection : 1;
|
||||
} ClutterStageViewPrivate;
|
||||
@@ -102,9 +111,9 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
if (priv->offscreen)
|
||||
return priv->offscreen;
|
||||
return COGL_FRAMEBUFFER (priv->offscreen);
|
||||
else if (priv->shadow.framebuffer)
|
||||
return priv->shadow.framebuffer;
|
||||
return COGL_FRAMEBUFFER (priv->shadow.framebuffer);
|
||||
else
|
||||
return priv->framebuffer;
|
||||
}
|
||||
@@ -127,8 +136,9 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
|
||||
clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen);
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
|
||||
@@ -137,7 +147,7 @@ clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0,
|
||||
cogl_offscreen_get_texture (framebuffer));
|
||||
cogl_offscreen_get_texture (offscreen));
|
||||
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
@@ -158,7 +168,7 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
return;
|
||||
|
||||
priv->offscreen_pipeline =
|
||||
clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
|
||||
clutter_stage_view_create_offscreen_pipeline (priv->offscreen);
|
||||
|
||||
if (view_class->setup_offscreen_blit_pipeline)
|
||||
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
|
||||
@@ -192,7 +202,7 @@ clutter_stage_view_transform_rect_to_onscreen (ClutterStageView *view
|
||||
static void
|
||||
paint_transformed_framebuffer (ClutterStageView *view,
|
||||
CoglPipeline *pipeline,
|
||||
CoglFramebuffer *src_framebuffer,
|
||||
CoglOffscreen *src_framebuffer,
|
||||
CoglFramebuffer *dst_framebuffer,
|
||||
const cairo_region_t *redraw_clip)
|
||||
{
|
||||
@@ -432,10 +442,13 @@ clutter_stage_view_after_paint (ClutterStageView *view,
|
||||
|
||||
if (priv->shadow.framebuffer)
|
||||
{
|
||||
CoglFramebuffer *shadowfb =
|
||||
COGL_FRAMEBUFFER (priv->shadow.framebuffer);
|
||||
|
||||
paint_transformed_framebuffer (view,
|
||||
priv->offscreen_pipeline,
|
||||
priv->offscreen,
|
||||
priv->shadow.framebuffer,
|
||||
shadowfb,
|
||||
redraw_clip);
|
||||
}
|
||||
else
|
||||
@@ -508,7 +521,7 @@ find_damaged_tiles (ClutterStageView *view,
|
||||
stride = cogl_dma_buf_handle_get_stride (current_dma_buf_handle);
|
||||
bpp = cogl_dma_buf_handle_get_bpp (current_dma_buf_handle);
|
||||
|
||||
cogl_framebuffer_finish (priv->shadow.framebuffer);
|
||||
cogl_framebuffer_finish (COGL_FRAMEBUFFER (priv->shadow.framebuffer));
|
||||
|
||||
if (!cogl_dma_buf_handle_sync_read_start (prev_dma_buf_handle, error))
|
||||
return NULL;
|
||||
@@ -601,7 +614,7 @@ swap_dma_buf_framebuffer (ClutterStageView *view)
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
int next_idx;
|
||||
CoglDmaBufHandle *next_dma_buf_handle;
|
||||
CoglOffscreen *next_framebuffer;
|
||||
CoglFramebuffer *next_framebuffer;
|
||||
|
||||
next_idx = ((priv->shadow.dma_buf.current_idx + 1) %
|
||||
G_N_ELEMENTS (priv->shadow.dma_buf.handles));
|
||||
@@ -697,12 +710,13 @@ copy_shadowfb_to_onscreen (ClutterStageView *view,
|
||||
|
||||
for (i = 0; i < cairo_region_num_rectangles (damage_region); i++)
|
||||
{
|
||||
CoglFramebuffer *shadowfb = COGL_FRAMEBUFFER (priv->shadow.framebuffer);
|
||||
g_autoptr (GError) error = NULL;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (damage_region, i, &rect);
|
||||
|
||||
if (!cogl_blit_framebuffer (priv->shadow.framebuffer,
|
||||
if (!cogl_blit_framebuffer (shadowfb,
|
||||
priv->framebuffer,
|
||||
rect.x, rect.y,
|
||||
rect.x, rect.y,
|
||||
@@ -754,7 +768,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
|
||||
|
||||
if (priv->offscreen)
|
||||
{
|
||||
callback (priv->offscreen, user_data);
|
||||
callback (COGL_FRAMEBUFFER (priv->offscreen), user_data);
|
||||
}
|
||||
else if (priv->shadow.framebuffer)
|
||||
{
|
||||
@@ -773,7 +787,7 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view,
|
||||
}
|
||||
else
|
||||
{
|
||||
callback (priv->shadow.framebuffer, user_data);
|
||||
callback (COGL_FRAMEBUFFER (priv->shadow.framebuffer), user_data);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -988,6 +1002,154 @@ clutter_stage_view_take_scanout (ClutterStageView *view)
|
||||
return g_steal_pointer (&priv->next_scanout);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_view_schedule_update (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
clutter_frame_clock_schedule_update (priv->frame_clock);
|
||||
}
|
||||
|
||||
float
|
||||
clutter_stage_view_get_refresh_rate (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
return priv->refresh_rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_view_get_frame_clock: (skip)
|
||||
*/
|
||||
ClutterFrameClock *
|
||||
clutter_stage_view_get_frame_clock (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
return priv->frame_clock;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_frame_clock_before_frame (ClutterFrameClock *frame_clock,
|
||||
int64_t frame_count,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterStageView *view = user_data;
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
_clutter_stage_process_queued_events (priv->stage);
|
||||
}
|
||||
|
||||
static ClutterFrameResult
|
||||
handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
||||
int64_t frame_count,
|
||||
int64_t time_us,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterStageView *view = user_data;
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
ClutterStage *stage = priv->stage;
|
||||
g_autoptr (GSList) devices = NULL;
|
||||
ClutterFrameResult result;
|
||||
|
||||
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||
return CLUTTER_FRAME_RESULT_IDLE;
|
||||
|
||||
if (!clutter_actor_is_realized (CLUTTER_ACTOR (stage)))
|
||||
return CLUTTER_FRAME_RESULT_IDLE;
|
||||
|
||||
if (!clutter_actor_is_mapped (CLUTTER_ACTOR (stage)))
|
||||
return CLUTTER_FRAME_RESULT_IDLE;
|
||||
|
||||
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_PRE_PAINT);
|
||||
clutter_stage_emit_before_update (stage, view);
|
||||
|
||||
clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
|
||||
clutter_stage_update_actor_stage_views (stage);
|
||||
clutter_stage_maybe_finish_queue_redraws (stage);
|
||||
|
||||
devices = clutter_stage_find_updated_devices (stage);
|
||||
|
||||
if (clutter_stage_view_has_redraw_clip (view))
|
||||
{
|
||||
ClutterStageWindow *stage_window;
|
||||
|
||||
clutter_stage_emit_before_paint (stage, view);
|
||||
|
||||
stage_window = _clutter_stage_get_window (stage);
|
||||
_clutter_stage_window_redraw_view (stage_window, view);
|
||||
|
||||
clutter_stage_emit_after_paint (stage, view);
|
||||
|
||||
_clutter_stage_window_finish_frame (stage_window);
|
||||
|
||||
result = CLUTTER_FRAME_RESULT_PENDING_PRESENTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CLUTTER_FRAME_RESULT_IDLE;
|
||||
}
|
||||
|
||||
clutter_stage_update_devices (stage, devices);
|
||||
|
||||
_clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
|
||||
clutter_stage_emit_after_update (stage, view);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const ClutterFrameListenerIface frame_clock_listener_iface = {
|
||||
.before_frame = handle_frame_clock_before_frame,
|
||||
.frame = handle_frame_clock_frame,
|
||||
};
|
||||
|
||||
void
|
||||
clutter_stage_view_notify_presented (ClutterStageView *view,
|
||||
ClutterFrameInfo *frame_info)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
clutter_stage_presented (priv->stage, view, frame_info);
|
||||
clutter_frame_clock_notify_presented (priv->frame_clock, frame_info);
|
||||
}
|
||||
|
||||
static void
|
||||
sanity_check_framebuffer (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
G_GNUC_UNUSED int fb_width, fb_height;
|
||||
|
||||
fb_width = cogl_framebuffer_get_width (priv->framebuffer);
|
||||
fb_height = cogl_framebuffer_get_height (priv->framebuffer);
|
||||
|
||||
g_warn_if_fail (fabsf (roundf (fb_width / priv->scale) -
|
||||
fb_width / priv->scale) < FLT_EPSILON);
|
||||
g_warn_if_fail (fabsf (roundf (fb_height / priv->scale) -
|
||||
fb_height / priv->scale) < FLT_EPSILON);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_set_framebuffer (ClutterStageView *view,
|
||||
CoglFramebuffer *framebuffer)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
g_warn_if_fail (!priv->framebuffer);
|
||||
if (framebuffer)
|
||||
{
|
||||
priv->framebuffer = cogl_object_ref (framebuffer);
|
||||
sanity_check_framebuffer (view);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
@@ -1003,6 +1165,9 @@ clutter_stage_view_get_property (GObject *object,
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, priv->name);
|
||||
break;
|
||||
case PROP_STAGE:
|
||||
g_value_set_boxed (value, &priv->stage);
|
||||
break;
|
||||
case PROP_LAYOUT:
|
||||
g_value_set_boxed (value, &priv->layout);
|
||||
break;
|
||||
@@ -1018,6 +1183,9 @@ clutter_stage_view_get_property (GObject *object,
|
||||
case PROP_SCALE:
|
||||
g_value_set_float (value, priv->scale);
|
||||
break;
|
||||
case PROP_REFRESH_RATE:
|
||||
g_value_set_float (value, priv->refresh_rate);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -1039,26 +1207,15 @@ clutter_stage_view_set_property (GObject *object,
|
||||
case PROP_NAME:
|
||||
priv->name = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_STAGE:
|
||||
priv->stage = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_LAYOUT:
|
||||
layout = g_value_get_boxed (value);
|
||||
priv->layout = *layout;
|
||||
break;
|
||||
case PROP_FRAMEBUFFER:
|
||||
priv->framebuffer = g_value_dup_boxed (value);
|
||||
#ifndef G_DISABLE_CHECKS
|
||||
if (priv->framebuffer)
|
||||
{
|
||||
int fb_width, fb_height;
|
||||
|
||||
fb_width = cogl_framebuffer_get_width (priv->framebuffer);
|
||||
fb_height = cogl_framebuffer_get_height (priv->framebuffer);
|
||||
|
||||
g_warn_if_fail (fabsf (roundf (fb_width / priv->scale) -
|
||||
fb_width / priv->scale) < FLT_EPSILON);
|
||||
g_warn_if_fail (fabsf (roundf (fb_height / priv->scale) -
|
||||
fb_height / priv->scale) < FLT_EPSILON);
|
||||
}
|
||||
#endif
|
||||
clutter_stage_view_set_framebuffer (view, g_value_get_boxed (value));
|
||||
break;
|
||||
case PROP_OFFSCREEN:
|
||||
priv->offscreen = g_value_dup_boxed (value);
|
||||
@@ -1069,6 +1226,9 @@ clutter_stage_view_set_property (GObject *object,
|
||||
case PROP_SCALE:
|
||||
priv->scale = g_value_get_float (value);
|
||||
break;
|
||||
case PROP_REFRESH_RATE:
|
||||
priv->refresh_rate = g_value_get_float (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@@ -1084,6 +1244,10 @@ clutter_stage_view_constructed (GObject *object)
|
||||
if (priv->use_shadowfb)
|
||||
init_shadowfb (view);
|
||||
|
||||
priv->frame_clock = clutter_frame_clock_new (priv->refresh_rate,
|
||||
&frame_clock_listener_iface,
|
||||
view);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_view_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
@@ -1110,6 +1274,7 @@ clutter_stage_view_dispose (GObject *object)
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->frame_clock, clutter_frame_clock_destroy);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -1123,6 +1288,7 @@ clutter_stage_view_init (ClutterStageView *view)
|
||||
priv->dirty_viewport = TRUE;
|
||||
priv->dirty_projection = TRUE;
|
||||
priv->scale = 1.0;
|
||||
priv->refresh_rate = 60.0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1146,6 +1312,16 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_STAGE] =
|
||||
g_param_spec_object ("stage",
|
||||
"The stage",
|
||||
"The ClutterStage",
|
||||
CLUTTER_TYPE_STAGE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_LAYOUT] =
|
||||
g_param_spec_boxed ("layout",
|
||||
"View layout",
|
||||
@@ -1191,5 +1367,14 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_REFRESH_RATE] =
|
||||
g_param_spec_float ("refresh-rate",
|
||||
"Refresh rate",
|
||||
"Update refresh rate",
|
||||
1.0, G_MAXFLOAT, 60.0,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#include "clutter-macros.h"
|
||||
#include "clutter-frame-clock.h"
|
||||
|
||||
#define CLUTTER_TYPE_STAGE_VIEW (clutter_stage_view_get_type ())
|
||||
CLUTTER_EXPORT
|
||||
@@ -69,4 +70,7 @@ CLUTTER_EXPORT
|
||||
void clutter_stage_view_get_offscreen_transformation_matrix (ClutterStageView *view,
|
||||
CoglMatrix *matrix);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_stage_view_get_frame_clock (ClutterStageView *view);
|
||||
|
||||
#endif /* __CLUTTER_STAGE_VIEW_H__ */
|
||||
|
@@ -103,81 +103,12 @@ _clutter_stage_window_get_geometry (ClutterStageWindow *window,
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_schedule_update (ClutterStageWindow *window,
|
||||
int sync_delay)
|
||||
_clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
||||
ClutterStageView *view)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->schedule_update == NULL)
|
||||
{
|
||||
g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
|
||||
return;
|
||||
}
|
||||
|
||||
iface->schedule_update (window, sync_delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* _clutter_stage_window_get_update_time:
|
||||
* @window: a #ClutterStageWindow object
|
||||
*
|
||||
* See _clutter_stage_get_update_time() for more info.
|
||||
*
|
||||
* Returns: The timestamp of the update time
|
||||
*/
|
||||
gint64
|
||||
_clutter_stage_window_get_update_time (ClutterStageWindow *window)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0);
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->get_update_time == NULL)
|
||||
{
|
||||
g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iface->get_update_time (window);
|
||||
}
|
||||
|
||||
/**
|
||||
* _clutter_stage_window_clear_update_time:
|
||||
* @window: a #ClutterStageWindow object
|
||||
*
|
||||
* Clears the update time. See _clutter_stage_clear_update_time() for more info.
|
||||
*/
|
||||
void
|
||||
_clutter_stage_window_clear_update_time (ClutterStageWindow *window)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->clear_update_time == NULL)
|
||||
{
|
||||
g_assert (!clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS));
|
||||
return;
|
||||
}
|
||||
|
||||
iface->clear_update_time (window);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_redraw (ClutterStageWindow *window)
|
||||
{
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_WINDOW (window));
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
if (iface->redraw)
|
||||
iface->redraw (window);
|
||||
CLUTTER_STAGE_WINDOW_GET_IFACE (window)->redraw_view (window, view);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -44,12 +44,8 @@ struct _ClutterStageWindowInterface
|
||||
void (* get_geometry) (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *geometry);
|
||||
|
||||
void (* schedule_update) (ClutterStageWindow *stage_window,
|
||||
int sync_delay);
|
||||
gint64 (* get_update_time) (ClutterStageWindow *stage_window);
|
||||
void (* clear_update_time) (ClutterStageWindow *stage_window);
|
||||
|
||||
void (* redraw) (ClutterStageWindow *stage_window);
|
||||
void (* redraw_view) (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view);
|
||||
|
||||
gboolean (* can_clip_redraws) (ClutterStageWindow *stage_window);
|
||||
|
||||
@@ -78,15 +74,12 @@ void _clutter_stage_window_resize (ClutterStageWin
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_stage_window_get_geometry (ClutterStageWindow *window,
|
||||
cairo_rectangle_int_t *geometry);
|
||||
void _clutter_stage_window_schedule_update (ClutterStageWindow *window,
|
||||
int sync_delay);
|
||||
gint64 _clutter_stage_window_get_update_time (ClutterStageWindow *window);
|
||||
void _clutter_stage_window_clear_update_time (ClutterStageWindow *window);
|
||||
|
||||
void _clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
|
||||
gboolean accept_focus);
|
||||
|
||||
void _clutter_stage_window_redraw (ClutterStageWindow *window);
|
||||
void _clutter_stage_window_redraw_view (ClutterStageWindow *window,
|
||||
ClutterStageView *view);
|
||||
|
||||
gboolean _clutter_stage_window_can_clip_redraws (ClutterStageWindow *window);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -28,8 +28,8 @@
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-group.h>
|
||||
#include <clutter/clutter-stage-view.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -56,7 +56,7 @@ typedef struct _ClutterStagePrivate ClutterStagePrivate;
|
||||
struct _ClutterStage
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterGroup parent_instance;
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterStagePrivate *priv;
|
||||
};
|
||||
@@ -74,7 +74,7 @@ struct _ClutterStage
|
||||
struct _ClutterStageClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterGroupClass parent_class;
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
/* signals */
|
||||
@@ -197,7 +197,8 @@ CLUTTER_EXPORT
|
||||
void clutter_stage_ensure_viewport (ClutterStage *stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_stage_is_redraw_queued (ClutterStage *stage);
|
||||
gboolean clutter_stage_is_redraw_queued_on_view (ClutterStage *stage,
|
||||
ClutterStageView *view);
|
||||
|
||||
#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||
CLUTTER_EXPORT
|
||||
|
@@ -187,9 +187,6 @@ struct _ClutterTextPrivate
|
||||
ClutterInputContentHintFlags input_hints;
|
||||
ClutterInputContentPurpose input_purpose;
|
||||
|
||||
/* Signal handler for when the :resource-scale changes */
|
||||
gulong resource_scale_changed_id;
|
||||
|
||||
/* bitfields */
|
||||
guint alignment : 2;
|
||||
guint wrap : 1;
|
||||
@@ -598,9 +595,7 @@ ensure_effective_pango_scale_attribute (ClutterText *self)
|
||||
float resource_scale;
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale) ||
|
||||
resource_scale == 1.0)
|
||||
return;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
if (priv->effective_attrs != NULL)
|
||||
{
|
||||
@@ -922,18 +917,6 @@ clutter_text_direction_changed_cb (GObject *gobject,
|
||||
/* no need to queue a relayout: set_text_direction() will do that for us */
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_text_resource_scale_changed_cb (GObject *gobject,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterText *self = CLUTTER_TEXT (gobject);
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref);
|
||||
clutter_text_dirty_cache (self);
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (gobject));
|
||||
}
|
||||
|
||||
/*
|
||||
* clutter_text_create_layout:
|
||||
* @text: a #ClutterText
|
||||
@@ -1137,8 +1120,7 @@ maybe_create_text_layout_with_resource_scale (ClutterText *text,
|
||||
{
|
||||
float resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (text), &resource_scale))
|
||||
return NULL;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (text));
|
||||
|
||||
return create_text_layout_with_scale (text,
|
||||
allocation_width,
|
||||
@@ -1170,8 +1152,7 @@ clutter_text_coords_to_position (ClutterText *self,
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXT (self), 0);
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
|
||||
return 0;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
/* Take any offset due to scrolling into account, and normalize
|
||||
* the coordinates to PangoScale units
|
||||
@@ -1299,8 +1280,7 @@ clutter_text_position_to_coords (ClutterText *self,
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXT (self), FALSE);
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
|
||||
return FALSE;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
ret = clutter_text_position_to_coords_internal (self, position,
|
||||
x, y, line_height);
|
||||
@@ -1776,7 +1756,6 @@ clutter_text_dispose (GObject *gobject)
|
||||
clutter_text_dirty_cache (self);
|
||||
|
||||
g_clear_signal_handler (&priv->direction_changed_id, self);
|
||||
g_clear_signal_handler (&priv->resource_scale_changed_id, self);
|
||||
g_clear_signal_handler (&priv->settings_changed_id,
|
||||
clutter_get_default_backend ());
|
||||
|
||||
@@ -2641,8 +2620,7 @@ clutter_text_paint (ClutterActor *self,
|
||||
!clutter_text_should_draw_cursor (text))
|
||||
return;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (CLUTTER_ACTOR (self), &resource_scale))
|
||||
return;
|
||||
resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (self));
|
||||
|
||||
clutter_actor_box_scale (&alloc, resource_scale);
|
||||
clutter_actor_box_get_size (&alloc, &alloc_width, &alloc_height);
|
||||
@@ -2874,8 +2852,7 @@ clutter_text_get_paint_volume (ClutterActor *self,
|
||||
if (!clutter_actor_has_allocation (self))
|
||||
return FALSE;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (self, &resource_scale))
|
||||
return FALSE;
|
||||
resource_scale = clutter_actor_get_resource_scale (self);
|
||||
|
||||
_clutter_paint_volume_init_static (&priv->paint_volume, self);
|
||||
|
||||
@@ -2932,8 +2909,7 @@ clutter_text_get_preferred_width (ClutterActor *self,
|
||||
gfloat layout_width;
|
||||
gfloat resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (self, &resource_scale))
|
||||
resource_scale = 1;
|
||||
resource_scale = clutter_actor_get_resource_scale (self);
|
||||
|
||||
layout = clutter_text_create_layout (text, -1, -1);
|
||||
pango_layout_get_extents (layout, NULL, &logical_rect);
|
||||
@@ -2989,8 +2965,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
||||
gfloat layout_height;
|
||||
gfloat resource_scale;
|
||||
|
||||
if (!clutter_actor_get_resource_scale (self, &resource_scale))
|
||||
resource_scale = 1;
|
||||
resource_scale = clutter_actor_get_resource_scale (self);
|
||||
|
||||
if (priv->single_line_mode)
|
||||
for_width = -1;
|
||||
@@ -3066,6 +3041,33 @@ clutter_text_has_overlaps (ClutterActor *self)
|
||||
return clutter_text_should_draw_cursor ((ClutterText *) self);
|
||||
}
|
||||
|
||||
static float
|
||||
clutter_text_calculate_resource_scale (ClutterActor *actor,
|
||||
int phase)
|
||||
{
|
||||
ClutterActorClass *parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
|
||||
float new_resource_scale;
|
||||
|
||||
new_resource_scale = parent_class->calculate_resource_scale (actor, phase);
|
||||
|
||||
if (phase == 1)
|
||||
return MAX (new_resource_scale, clutter_actor_get_real_resource_scale (actor));
|
||||
|
||||
return new_resource_scale;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_text_resource_scale_changed (ClutterActor *actor)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (actor);
|
||||
ClutterTextPrivate *priv = text->priv;
|
||||
|
||||
g_clear_pointer (&priv->effective_attrs, pango_attr_list_unref);
|
||||
clutter_text_dirty_cache (text);
|
||||
|
||||
clutter_actor_queue_immediate_relayout (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_text_im_focus (ClutterText *text)
|
||||
{
|
||||
@@ -3814,6 +3816,8 @@ clutter_text_class_init (ClutterTextClass *klass)
|
||||
actor_class->key_focus_in = clutter_text_key_focus_in;
|
||||
actor_class->key_focus_out = clutter_text_key_focus_out;
|
||||
actor_class->has_overlaps = clutter_text_has_overlaps;
|
||||
actor_class->calculate_resource_scale = clutter_text_calculate_resource_scale;
|
||||
actor_class->resource_scale_changed = clutter_text_resource_scale_changed;
|
||||
|
||||
/**
|
||||
* ClutterText:buffer:
|
||||
@@ -4621,11 +4625,6 @@ clutter_text_init (ClutterText *self)
|
||||
NULL);
|
||||
|
||||
priv->input_focus = clutter_text_input_focus_new (self);
|
||||
|
||||
priv->resource_scale_changed_id =
|
||||
g_signal_connect (self, "notify::resource-scale",
|
||||
G_CALLBACK (clutter_text_resource_scale_changed_cb),
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
33
clutter/clutter/clutter-timeline-private.h
Normal file
33
clutter/clutter/clutter-timeline-private.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CLUTTER_TIMELINE_PRIVATE_H
|
||||
#define CLUTTER_TIMELINE_PRIVATE_H
|
||||
|
||||
void _clutter_timeline_advance (ClutterTimeline *timeline,
|
||||
int64_t tick_time);
|
||||
int64_t _clutter_timeline_get_delta (ClutterTimeline *timeline);
|
||||
void _clutter_timeline_do_tick (ClutterTimeline *timeline,
|
||||
int64_t tick_time);
|
||||
|
||||
#endif /* CLUTTER_TIMELINE_PRIVATE_H */
|
@@ -95,22 +95,31 @@
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-timeline.h"
|
||||
#include "deprecated/clutter-timeline.h"
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-easing.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-frame-clock.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-scriptable.h"
|
||||
|
||||
#include "deprecated/clutter-timeline.h"
|
||||
#include "clutter-timeline-private.h"
|
||||
|
||||
struct _ClutterTimelinePrivate
|
||||
{
|
||||
ClutterTimelineDirection direction;
|
||||
|
||||
ClutterFrameClock *custom_frame_clock;
|
||||
ClutterFrameClock *frame_clock;
|
||||
|
||||
ClutterActor *actor;
|
||||
gulong actor_destroy_handler_id;
|
||||
gulong actor_stage_views_handler_id;
|
||||
gulong stage_stage_views_handler_id;
|
||||
ClutterActor *stage;
|
||||
|
||||
guint delay_id;
|
||||
|
||||
/* The total length in milliseconds of this timeline */
|
||||
@@ -172,12 +181,14 @@ enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_ACTOR,
|
||||
PROP_DELAY,
|
||||
PROP_DURATION,
|
||||
PROP_DIRECTION,
|
||||
PROP_AUTO_REVERSE,
|
||||
PROP_REPEAT_COUNT,
|
||||
PROP_PROGRESS_MODE,
|
||||
PROP_FRAME_CLOCK,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@@ -198,6 +209,8 @@ enum
|
||||
|
||||
static guint timeline_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void update_frame_clock (ClutterTimeline *timeline);
|
||||
|
||||
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterTimeline, clutter_timeline, G_TYPE_OBJECT,
|
||||
@@ -289,6 +302,177 @@ clutter_timeline_add_marker_internal (ClutterTimeline *timeline,
|
||||
g_hash_table_insert (priv->markers_by_name, marker->name, marker);
|
||||
}
|
||||
|
||||
static void
|
||||
on_actor_destroyed (ClutterActor *actor,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
priv->actor = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_get_actor:
|
||||
* @timeline: a #ClutterTimeline
|
||||
*
|
||||
* Get the actor the timeline is associated with.
|
||||
*
|
||||
* Returns: (transfer none): the associated #ClutterActor
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_timeline_get_actor (ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
return priv->actor;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_add_timeline (ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
if (!priv->frame_clock)
|
||||
return;
|
||||
|
||||
clutter_frame_clock_add_timeline (priv->frame_clock, timeline);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_remove_timeline (ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
if (!priv->frame_clock)
|
||||
return;
|
||||
|
||||
clutter_frame_clock_remove_timeline (priv->frame_clock, timeline);
|
||||
}
|
||||
|
||||
static void
|
||||
set_frame_clock_internal (ClutterTimeline *timeline,
|
||||
ClutterFrameClock *frame_clock)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
if (priv->frame_clock == frame_clock)
|
||||
return;
|
||||
|
||||
if (priv->frame_clock && priv->is_playing)
|
||||
maybe_remove_timeline (timeline);
|
||||
|
||||
g_set_object (&priv->frame_clock, frame_clock);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (timeline),
|
||||
obj_props[PROP_FRAME_CLOCK]);
|
||||
|
||||
if (priv->is_playing)
|
||||
maybe_add_timeline (timeline);
|
||||
}
|
||||
|
||||
static void
|
||||
on_stage_stage_views_changed (ClutterActor *stage,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
|
||||
priv->stage = NULL;
|
||||
|
||||
update_frame_clock (timeline);
|
||||
}
|
||||
|
||||
static void
|
||||
update_frame_clock (ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
ClutterFrameClock *frame_clock = NULL;
|
||||
ClutterActor *stage;
|
||||
|
||||
if (!priv->actor)
|
||||
goto out;
|
||||
|
||||
frame_clock = clutter_actor_pick_frame_clock (priv->actor);
|
||||
if (frame_clock)
|
||||
{
|
||||
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
|
||||
goto out;
|
||||
}
|
||||
|
||||
stage = clutter_actor_get_stage (priv->actor);
|
||||
if (!stage)
|
||||
{
|
||||
if (priv->is_playing)
|
||||
g_warning ("Timelines with detached actors are not supported");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (priv->stage_stage_views_handler_id > 0)
|
||||
goto out;
|
||||
|
||||
priv->stage_stage_views_handler_id =
|
||||
g_signal_connect (stage, "stage-views-changed",
|
||||
G_CALLBACK (on_stage_stage_views_changed),
|
||||
timeline);
|
||||
priv->stage = stage;
|
||||
|
||||
out:
|
||||
set_frame_clock_internal (timeline, frame_clock);
|
||||
}
|
||||
|
||||
static void
|
||||
on_actor_stage_views_changed (ClutterActor *actor,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
update_frame_clock (timeline);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_set_actor:
|
||||
* @timeline: a #ClutterTimeline
|
||||
* @actor: (nullable): a #ClutterActor
|
||||
*
|
||||
* Set the actor the timeline is associated with.
|
||||
*/
|
||||
void
|
||||
clutter_timeline_set_actor (ClutterTimeline *timeline,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
|
||||
g_return_if_fail (!actor || (actor && !priv->custom_frame_clock));
|
||||
|
||||
if (priv->actor)
|
||||
{
|
||||
g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor);
|
||||
g_clear_signal_handler (&priv->actor_stage_views_handler_id, priv->actor);
|
||||
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
|
||||
priv->stage = NULL;
|
||||
priv->actor = NULL;
|
||||
|
||||
if (priv->is_playing)
|
||||
maybe_remove_timeline (timeline);
|
||||
|
||||
priv->frame_clock = NULL;
|
||||
}
|
||||
|
||||
priv->actor = actor;
|
||||
|
||||
if (priv->actor)
|
||||
{
|
||||
priv->actor_destroy_handler_id =
|
||||
g_signal_connect (priv->actor, "destroy",
|
||||
G_CALLBACK (on_actor_destroyed),
|
||||
timeline);
|
||||
priv->actor_stage_views_handler_id =
|
||||
g_signal_connect (priv->actor, "stage-views-changed",
|
||||
G_CALLBACK (on_actor_stage_views_changed),
|
||||
timeline);
|
||||
}
|
||||
|
||||
update_frame_clock (timeline);
|
||||
}
|
||||
|
||||
/* Scriptable */
|
||||
typedef struct _ParseClosure {
|
||||
ClutterTimeline *timeline;
|
||||
@@ -430,6 +614,10 @@ clutter_timeline_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTOR:
|
||||
clutter_timeline_set_actor (timeline, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_DELAY:
|
||||
clutter_timeline_set_delay (timeline, g_value_get_uint (value));
|
||||
break;
|
||||
@@ -454,6 +642,10 @@ clutter_timeline_set_property (GObject *object,
|
||||
clutter_timeline_set_progress_mode (timeline, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_FRAME_CLOCK:
|
||||
clutter_timeline_set_frame_clock (timeline, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -471,6 +663,10 @@ clutter_timeline_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ACTOR:
|
||||
g_value_set_object (value, priv->actor);
|
||||
break;
|
||||
|
||||
case PROP_DELAY:
|
||||
g_value_set_uint (value, priv->delay);
|
||||
break;
|
||||
@@ -495,6 +691,10 @@ clutter_timeline_get_property (GObject *object,
|
||||
g_value_set_enum (value, priv->progress_mode);
|
||||
break;
|
||||
|
||||
case PROP_FRAME_CLOCK:
|
||||
g_value_set_object (value, priv->frame_clock);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -506,16 +706,14 @@ clutter_timeline_finalize (GObject *object)
|
||||
{
|
||||
ClutterTimeline *self = CLUTTER_TIMELINE (object);
|
||||
ClutterTimelinePrivate *priv = self->priv;
|
||||
ClutterMasterClock *master_clock;
|
||||
|
||||
if (priv->markers_by_name)
|
||||
g_hash_table_destroy (priv->markers_by_name);
|
||||
|
||||
if (priv->is_playing)
|
||||
{
|
||||
master_clock = _clutter_master_clock_get_default ();
|
||||
_clutter_master_clock_remove_timeline (master_clock, self);
|
||||
}
|
||||
maybe_remove_timeline (self);
|
||||
|
||||
g_clear_object (&priv->frame_clock);
|
||||
|
||||
G_OBJECT_CLASS (clutter_timeline_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -530,6 +728,14 @@ clutter_timeline_dispose (GObject *object)
|
||||
|
||||
clutter_timeline_cancel_delay (self);
|
||||
|
||||
if (priv->actor)
|
||||
{
|
||||
g_clear_signal_handler (&priv->actor_destroy_handler_id, priv->actor);
|
||||
g_clear_signal_handler (&priv->actor_stage_views_handler_id, priv->actor);
|
||||
g_clear_signal_handler (&priv->stage_stage_views_handler_id, priv->stage);
|
||||
priv->actor = NULL;
|
||||
}
|
||||
|
||||
if (priv->progress_notify != NULL)
|
||||
{
|
||||
priv->progress_notify (priv->progress_data);
|
||||
@@ -546,6 +752,18 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
/**
|
||||
* ClutterTimeline::actor:
|
||||
*
|
||||
* The actor the timeline is associated with. This will determine what frame
|
||||
* clock will drive it.
|
||||
*/
|
||||
obj_props[PROP_ACTOR] =
|
||||
g_param_spec_object ("actor",
|
||||
P_("Actor"),
|
||||
P_("Associated ClutterActor"),
|
||||
CLUTTER_TYPE_ACTOR,
|
||||
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
|
||||
/**
|
||||
* ClutterTimeline:delay:
|
||||
*
|
||||
@@ -644,6 +862,18 @@ clutter_timeline_class_init (ClutterTimelineClass *klass)
|
||||
CLUTTER_LINEAR,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
|
||||
/**
|
||||
* ClutterTimeline:frame-clock:
|
||||
*
|
||||
* The frame clock driving the timeline.
|
||||
*/
|
||||
obj_props[PROP_FRAME_CLOCK] =
|
||||
g_param_spec_object ("frame-clock",
|
||||
"Frame clock",
|
||||
"Frame clock driving the timeline",
|
||||
CLUTTER_TYPE_FRAME_CLOCK,
|
||||
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE);
|
||||
|
||||
object_class->dispose = clutter_timeline_dispose;
|
||||
object_class->finalize = clutter_timeline_finalize;
|
||||
object_class->set_property = clutter_timeline_set_property;
|
||||
@@ -926,7 +1156,6 @@ set_is_playing (ClutterTimeline *timeline,
|
||||
gboolean is_playing)
|
||||
{
|
||||
ClutterTimelinePrivate *priv = timeline->priv;
|
||||
ClutterMasterClock *master_clock;
|
||||
|
||||
is_playing = !!is_playing;
|
||||
|
||||
@@ -935,15 +1164,17 @@ set_is_playing (ClutterTimeline *timeline,
|
||||
|
||||
priv->is_playing = is_playing;
|
||||
|
||||
master_clock = _clutter_master_clock_get_default ();
|
||||
if (priv->is_playing)
|
||||
{
|
||||
priv->waiting_first_tick = TRUE;
|
||||
priv->current_repeat = 0;
|
||||
_clutter_master_clock_add_timeline (master_clock, timeline);
|
||||
|
||||
maybe_add_timeline (timeline);
|
||||
}
|
||||
else
|
||||
_clutter_master_clock_remove_timeline (master_clock, timeline);
|
||||
{
|
||||
maybe_remove_timeline (timeline);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1140,6 +1371,9 @@ clutter_timeline_start (ClutterTimeline *timeline)
|
||||
if (priv->duration == 0)
|
||||
return;
|
||||
|
||||
g_warn_if_fail ((priv->actor && clutter_actor_get_stage (priv->actor)) ||
|
||||
priv->frame_clock);
|
||||
|
||||
if (priv->delay)
|
||||
priv->delay_id = clutter_threads_add_timeout (priv->delay,
|
||||
delay_timeout_func,
|
||||
@@ -1340,6 +1574,46 @@ clutter_timeline_new (guint duration_ms)
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_new_for_actor:
|
||||
* @actor: The #ClutterActor the timeline is associated with
|
||||
* @duration_ms: Duration of the timeline in milliseconds
|
||||
*
|
||||
* Creates a new #ClutterTimeline with a duration of @duration milli seconds.
|
||||
*
|
||||
* Return value: the newly created #ClutterTimeline instance. Use
|
||||
* g_object_unref() when done using it
|
||||
*/
|
||||
ClutterTimeline *
|
||||
clutter_timeline_new_for_actor (ClutterActor *actor,
|
||||
unsigned int duration_ms)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_TIMELINE,
|
||||
"duration", duration_ms,
|
||||
"actor", actor,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_new_for_frame_clock:
|
||||
* @frame_clock: The #ClutterFrameClock the timeline is driven by
|
||||
* @duration_ms: Duration of the timeline in milliseconds
|
||||
*
|
||||
* Creates a new #ClutterTimeline with a duration of @duration_ms milli seconds.
|
||||
*
|
||||
* Return value: the newly created #ClutterTimeline instance. Use
|
||||
* g_object_unref() when done using it
|
||||
*/
|
||||
ClutterTimeline *
|
||||
clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock,
|
||||
unsigned int duration_ms)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_TIMELINE,
|
||||
"duration", duration_ms,
|
||||
"frame-clock", frame_clock,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_get_delay:
|
||||
* @timeline: a #ClutterTimeline
|
||||
@@ -1602,7 +1876,7 @@ _clutter_timeline_do_tick (ClutterTimeline *timeline,
|
||||
|
||||
/* Check the is_playing variable before performing the timeline tick.
|
||||
* This is necessary, as if a timeline is stopped in response to a
|
||||
* master-clock generated signal of a different timeline, this code can
|
||||
* frame clock generated signal of a different timeline, this code can
|
||||
* still be reached.
|
||||
*/
|
||||
if (!priv->is_playing)
|
||||
@@ -2420,3 +2694,32 @@ clutter_timeline_get_cubic_bezier_progress (ClutterTimeline *timeline,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_timeline_get_frame_clock: (skip)
|
||||
*/
|
||||
ClutterFrameClock *
|
||||
clutter_timeline_get_frame_clock (ClutterTimeline *timeline)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_TIMELINE (timeline), NULL);
|
||||
|
||||
return timeline->priv->frame_clock;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_timeline_set_frame_clock (ClutterTimeline *timeline,
|
||||
ClutterFrameClock *frame_clock)
|
||||
{
|
||||
ClutterTimelinePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_TIMELINE (timeline));
|
||||
|
||||
priv = timeline->priv;
|
||||
|
||||
g_assert (!frame_clock || (frame_clock && !priv->actor));
|
||||
g_return_if_fail (!frame_clock || (frame_clock && !priv->actor));
|
||||
|
||||
priv->custom_frame_clock = frame_clock;
|
||||
if (!priv->actor)
|
||||
set_frame_clock_internal (timeline, frame_clock);
|
||||
}
|
||||
|
@@ -119,7 +119,19 @@ CLUTTER_EXPORT
|
||||
GType clutter_timeline_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterTimeline * clutter_timeline_new (guint duration_ms);
|
||||
ClutterTimeline * clutter_timeline_new_for_actor (ClutterActor *actor,
|
||||
unsigned int duration_ms);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterTimeline * clutter_timeline_new_for_frame_clock (ClutterFrameClock *frame_clock,
|
||||
unsigned int duration_ms);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_timeline_get_actor (ClutterTimeline *timeline);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_timeline_set_actor (ClutterTimeline *timeline,
|
||||
ClutterActor *actor);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_timeline_get_duration (ClutterTimeline *timeline);
|
||||
@@ -221,6 +233,13 @@ gint64 clutter_timeline_get_duration_hint
|
||||
CLUTTER_EXPORT
|
||||
gint clutter_timeline_get_current_repeat (ClutterTimeline *timeline);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_timeline_get_frame_clock (ClutterTimeline *timeline);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_timeline_set_frame_clock (ClutterTimeline *timeline,
|
||||
ClutterFrameClock *frame_clock);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _CLUTTER_TIMELINE_H__ */
|
||||
|
@@ -43,6 +43,7 @@
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-timeline-private.h"
|
||||
|
||||
struct _ClutterTransitionGroupPrivate
|
||||
{
|
||||
|
@@ -364,6 +364,7 @@ clutter_transition_set_animatable (ClutterTransition *transition,
|
||||
ClutterAnimatable *animatable)
|
||||
{
|
||||
ClutterTransitionPrivate *priv;
|
||||
ClutterActor *actor;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_TRANSITION (transition));
|
||||
g_return_if_fail (animatable == NULL || CLUTTER_IS_ANIMATABLE (animatable));
|
||||
@@ -383,6 +384,9 @@ clutter_transition_set_animatable (ClutterTransition *transition,
|
||||
priv->animatable = g_object_ref (animatable);
|
||||
clutter_transition_attach (transition, priv->animatable);
|
||||
}
|
||||
|
||||
actor = clutter_animatable_get_actor (animatable);
|
||||
clutter_timeline_set_actor (CLUTTER_TIMELINE (transition), actor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -57,6 +57,7 @@ typedef struct _ClutterActorIter ClutterActorIter;
|
||||
typedef struct _ClutterPaintNode ClutterPaintNode;
|
||||
typedef struct _ClutterContent ClutterContent; /* dummy */
|
||||
typedef struct _ClutterScrollActor ClutterScrollActor;
|
||||
typedef struct _ClutterFrameClock ClutterFrameClock;
|
||||
|
||||
typedef struct _ClutterInterval ClutterInterval;
|
||||
typedef struct _ClutterAnimatable ClutterAnimatable; /* dummy */
|
||||
|
@@ -63,9 +63,9 @@
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-fixed-layout.h"
|
||||
#include "clutter-flow-layout.h"
|
||||
#include "clutter-frame-clock.h"
|
||||
#include "clutter-gesture-action.h"
|
||||
#include "clutter-grid-layout.h"
|
||||
#include "clutter-group.h"
|
||||
#include "clutter-image.h"
|
||||
#include "clutter-input-device.h"
|
||||
#include "clutter-input-device-tool.h"
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-stage-view-private.h"
|
||||
#include "cogl.h"
|
||||
|
||||
#define MAX_STACK_RECTS 256
|
||||
|
||||
@@ -55,17 +56,25 @@ typedef struct _ClutterStageViewCoglPrivate
|
||||
/* Damage history, in stage view render target framebuffer coordinate space.
|
||||
*/
|
||||
ClutterDamageHistory *damage_history;
|
||||
|
||||
guint notify_presented_handle_id;
|
||||
} ClutterStageViewCoglPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageViewCogl, clutter_stage_view_cogl,
|
||||
CLUTTER_TYPE_STAGE_VIEW)
|
||||
|
||||
typedef struct _ClutterStageCoglPrivate
|
||||
{
|
||||
int64_t global_frame_counter;
|
||||
} ClutterStageCoglPrivate;
|
||||
|
||||
static void
|
||||
clutter_stage_window_iface_init (ClutterStageWindowInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
|
||||
_clutter_stage_cogl,
|
||||
G_TYPE_OBJECT,
|
||||
G_ADD_PRIVATE (ClutterStageCogl)
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||
clutter_stage_window_iface_init));
|
||||
|
||||
@@ -77,67 +86,12 @@ enum
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
|
||||
gint sync_delay);
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_window);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_cogl_presented (ClutterStageCogl *stage_cogl,
|
||||
CoglFrameEvent frame_event,
|
||||
ClutterFrameInfo *frame_info)
|
||||
{
|
||||
|
||||
if (frame_event == COGL_FRAME_EVENT_SYNC)
|
||||
{
|
||||
/* Early versions of the swap_event implementation in Mesa
|
||||
* deliver BufferSwapComplete event when not selected for,
|
||||
* so if we get a swap event we aren't expecting, just ignore it.
|
||||
*
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=27962
|
||||
*
|
||||
* FIXME: This issue can be hidden inside Cogl so we shouldn't
|
||||
* need to care about this bug here.
|
||||
*/
|
||||
if (stage_cogl->pending_swaps > 0)
|
||||
stage_cogl->pending_swaps--;
|
||||
}
|
||||
else if (frame_event == COGL_FRAME_EVENT_COMPLETE)
|
||||
{
|
||||
gint64 presentation_time_cogl = frame_info->presentation_time;
|
||||
|
||||
if (presentation_time_cogl != 0)
|
||||
{
|
||||
ClutterBackend *backend = stage_cogl->backend;
|
||||
CoglContext *context = clutter_backend_get_cogl_context (backend);
|
||||
gint64 current_time_cogl = cogl_get_clock_time (context);
|
||||
gint64 now = g_get_monotonic_time ();
|
||||
|
||||
stage_cogl->last_presentation_time =
|
||||
now + (presentation_time_cogl - current_time_cogl) / 1000;
|
||||
}
|
||||
|
||||
stage_cogl->refresh_rate = frame_info->refresh_rate;
|
||||
}
|
||||
|
||||
_clutter_stage_presented (stage_cogl->wrapper, frame_event, frame_info);
|
||||
|
||||
if (frame_event == COGL_FRAME_EVENT_COMPLETE &&
|
||||
stage_cogl->update_time != -1)
|
||||
{
|
||||
ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl);
|
||||
|
||||
stage_cogl->update_time = -1;
|
||||
clutter_stage_cogl_schedule_update (stage_window,
|
||||
stage_cogl->last_sync_delay);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
|
||||
{
|
||||
@@ -158,101 +112,14 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
|
||||
gint sync_delay)
|
||||
static int64_t
|
||||
clutter_stage_cogl_get_frame_counter (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
gint64 now;
|
||||
float refresh_rate;
|
||||
gint64 refresh_interval;
|
||||
int64_t min_render_time_allowed;
|
||||
int64_t max_render_time_allowed;
|
||||
int64_t next_presentation_time;
|
||||
ClutterStageCoglPrivate *priv =
|
||||
_clutter_stage_cogl_get_instance_private (stage_cogl);
|
||||
|
||||
if (stage_cogl->update_time != -1)
|
||||
return;
|
||||
|
||||
stage_cogl->last_sync_delay = sync_delay;
|
||||
|
||||
now = g_get_monotonic_time ();
|
||||
|
||||
if (sync_delay < 0)
|
||||
{
|
||||
stage_cogl->update_time = now;
|
||||
return;
|
||||
}
|
||||
|
||||
refresh_rate = stage_cogl->refresh_rate;
|
||||
if (refresh_rate <= 0.0)
|
||||
refresh_rate = clutter_get_default_frame_rate ();
|
||||
|
||||
refresh_interval = (gint64) (0.5 + G_USEC_PER_SEC / refresh_rate);
|
||||
if (refresh_interval == 0)
|
||||
{
|
||||
stage_cogl->update_time = now;
|
||||
return;
|
||||
}
|
||||
|
||||
min_render_time_allowed = refresh_interval / 2;
|
||||
max_render_time_allowed = refresh_interval - 1000 * sync_delay;
|
||||
|
||||
/* Be robust in the case of incredibly bogus refresh rate */
|
||||
if (max_render_time_allowed <= 0)
|
||||
{
|
||||
g_warning ("Unsupported monitor refresh rate detected. "
|
||||
"(Refresh rate: %.3f, refresh interval: %" G_GINT64_FORMAT ")",
|
||||
refresh_rate,
|
||||
refresh_interval);
|
||||
stage_cogl->update_time = now;
|
||||
return;
|
||||
}
|
||||
|
||||
if (min_render_time_allowed > max_render_time_allowed)
|
||||
min_render_time_allowed = max_render_time_allowed;
|
||||
|
||||
next_presentation_time = stage_cogl->last_presentation_time + refresh_interval;
|
||||
|
||||
/* Get next_presentation_time closer to its final value, to reduce
|
||||
* the number of while iterations below.
|
||||
*/
|
||||
if (next_presentation_time < now)
|
||||
{
|
||||
int64_t last_virtual_presentation_time = now - now % refresh_interval;
|
||||
int64_t hardware_clock_phase =
|
||||
stage_cogl->last_presentation_time % refresh_interval;
|
||||
|
||||
next_presentation_time =
|
||||
last_virtual_presentation_time + hardware_clock_phase;
|
||||
}
|
||||
|
||||
while (next_presentation_time < now + min_render_time_allowed)
|
||||
next_presentation_time += refresh_interval;
|
||||
|
||||
stage_cogl->update_time = next_presentation_time - max_render_time_allowed;
|
||||
|
||||
if (stage_cogl->update_time == stage_cogl->last_update_time)
|
||||
stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval;
|
||||
}
|
||||
|
||||
static gint64
|
||||
clutter_stage_cogl_get_update_time (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
if (stage_cogl->pending_swaps)
|
||||
return -1; /* in the future, indefinite */
|
||||
|
||||
return stage_cogl->update_time;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
stage_cogl->last_update_time = stage_cogl->update_time;
|
||||
stage_cogl->update_time = -1;
|
||||
return priv->global_frame_counter;
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
@@ -355,12 +222,35 @@ paint_damage_region (ClutterStageWindow *stage_window,
|
||||
cogl_framebuffer_pop_matrix (framebuffer);
|
||||
}
|
||||
|
||||
typedef struct _NotifyPresentedClosure
|
||||
{
|
||||
ClutterStageView *view;
|
||||
ClutterFrameInfo frame_info;
|
||||
} NotifyPresentedClosure;
|
||||
|
||||
static gboolean
|
||||
notify_presented_idle (gpointer user_data)
|
||||
{
|
||||
NotifyPresentedClosure *closure = user_data;
|
||||
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (closure->view);
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
|
||||
view_priv->notify_presented_handle_id = 0;
|
||||
clutter_stage_view_notify_presented (closure->view, &closure->frame_info);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view,
|
||||
cairo_region_t *swap_region,
|
||||
gboolean swap_with_damage)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
ClutterStageCoglPrivate *priv =
|
||||
_clutter_stage_cogl_get_instance_private (stage_cogl);
|
||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
|
||||
|
||||
clutter_stage_view_before_swap_buffer (view, swap_region);
|
||||
@@ -369,6 +259,7 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
int *damage, n_rects, i;
|
||||
CoglFrameInfo *frame_info;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (swap_region);
|
||||
damage = g_newa (int, n_rects * 4);
|
||||
@@ -383,6 +274,9 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
damage[i * 4 + 3] = rect.height;
|
||||
}
|
||||
|
||||
frame_info = cogl_frame_info_new (priv->global_frame_counter);
|
||||
priv->global_frame_counter++;
|
||||
|
||||
/* push on the screen */
|
||||
if (n_rects > 0 && !swap_with_damage)
|
||||
{
|
||||
@@ -391,9 +285,8 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
onscreen);
|
||||
|
||||
cogl_onscreen_swap_region (onscreen,
|
||||
damage, n_rects);
|
||||
|
||||
return FALSE;
|
||||
damage, n_rects,
|
||||
frame_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -401,18 +294,35 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
onscreen);
|
||||
|
||||
cogl_onscreen_swap_buffers_with_damage (onscreen,
|
||||
damage, n_rects);
|
||||
|
||||
return TRUE;
|
||||
damage, n_rects,
|
||||
frame_info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
NotifyPresentedClosure *closure;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "cogl_framebuffer_finish (framebuffer: %p)",
|
||||
framebuffer);
|
||||
cogl_framebuffer_finish (framebuffer);
|
||||
|
||||
return FALSE;
|
||||
closure = g_new0 (NotifyPresentedClosure, 1);
|
||||
closure->view = view;
|
||||
closure->frame_info = (ClutterFrameInfo) {
|
||||
.frame_counter = priv->global_frame_counter,
|
||||
.refresh_rate = clutter_stage_view_get_refresh_rate (view),
|
||||
.presentation_time = g_get_monotonic_time (),
|
||||
};
|
||||
priv->global_frame_counter++;
|
||||
|
||||
g_warn_if_fail (view_priv->notify_presented_handle_id == 0);
|
||||
view_priv->notify_presented_handle_id =
|
||||
g_idle_add_full (G_PRIORITY_DEFAULT,
|
||||
notify_presented_idle,
|
||||
closure, g_free);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -539,11 +449,11 @@ is_buffer_age_enabled (void)
|
||||
cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view)
|
||||
static void
|
||||
clutter_stage_cogl_redraw_view_primary (ClutterStageCogl *stage_cogl,
|
||||
ClutterStageView *view)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_cogl);
|
||||
ClutterStageViewCogl *view_cogl = CLUTTER_STAGE_VIEW_COGL (view);
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
@@ -562,7 +472,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
float fb_scale;
|
||||
int fb_width, fb_height;
|
||||
int buffer_age = 0;
|
||||
gboolean res;
|
||||
|
||||
clutter_stage_view_get_layout (view, &view_rect);
|
||||
fb_scale = clutter_stage_view_get_scale (view);
|
||||
@@ -629,7 +538,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
redraw_clip = cairo_region_create_rectangle (&view_rect);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (!cairo_region_is_empty (fb_clip_region), FALSE);
|
||||
g_return_if_fail (!cairo_region_is_empty (fb_clip_region));
|
||||
|
||||
swap_with_damage = FALSE;
|
||||
if (has_buffer_age)
|
||||
@@ -730,14 +639,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
cairo_region_destroy (queued_redraw_clip);
|
||||
}
|
||||
|
||||
res = swap_framebuffer (stage_window,
|
||||
view,
|
||||
swap_region,
|
||||
swap_with_damage);
|
||||
swap_framebuffer (stage_window,
|
||||
view,
|
||||
swap_region,
|
||||
swap_with_damage);
|
||||
|
||||
cairo_region_destroy (swap_region);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -745,62 +652,34 @@ clutter_stage_cogl_scanout_view (ClutterStageCogl *stage_cogl,
|
||||
ClutterStageView *view,
|
||||
CoglScanout *scanout)
|
||||
{
|
||||
ClutterStageCoglPrivate *priv =
|
||||
_clutter_stage_cogl_get_instance_private (stage_cogl);
|
||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
|
||||
CoglOnscreen *onscreen;
|
||||
CoglFrameInfo *frame_info;
|
||||
|
||||
g_return_if_fail (cogl_is_onscreen (framebuffer));
|
||||
|
||||
onscreen = COGL_ONSCREEN (framebuffer);
|
||||
cogl_onscreen_direct_scanout (onscreen, scanout);
|
||||
|
||||
frame_info = cogl_frame_info_new (priv->global_frame_counter);
|
||||
priv->global_frame_counter++;
|
||||
|
||||
cogl_onscreen_direct_scanout (onscreen, scanout, frame_info);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
gboolean swap_event = FALSE;
|
||||
GList *l;
|
||||
g_autoptr (CoglScanout) scanout = NULL;
|
||||
|
||||
COGL_TRACE_BEGIN (ClutterStageCoglRedraw, "Paint (Cogl Redraw)");
|
||||
|
||||
for (l = _clutter_stage_window_get_views (stage_window); l; l = l->next)
|
||||
{
|
||||
ClutterStageView *view = l->data;
|
||||
g_autoptr (CoglScanout) scanout = NULL;
|
||||
|
||||
if (!clutter_stage_view_has_redraw_clip (view))
|
||||
continue;
|
||||
|
||||
scanout = clutter_stage_view_take_scanout (view);
|
||||
if (scanout)
|
||||
{
|
||||
clutter_stage_cogl_scanout_view (stage_cogl,
|
||||
view,
|
||||
scanout);
|
||||
swap_event = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
swap_event |= clutter_stage_cogl_redraw_view (stage_window, view);
|
||||
}
|
||||
}
|
||||
|
||||
_clutter_stage_emit_after_paint (stage_cogl->wrapper);
|
||||
|
||||
_clutter_stage_window_finish_frame (stage_window);
|
||||
|
||||
if (swap_event)
|
||||
{
|
||||
/* If we have swap buffer events then cogl_onscreen_swap_buffers
|
||||
* will return immediately and we need to track that there is a
|
||||
* swap in progress... */
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
|
||||
stage_cogl->pending_swaps++;
|
||||
}
|
||||
|
||||
stage_cogl->frame_count++;
|
||||
|
||||
COGL_TRACE_END (ClutterStageCoglRedraw);
|
||||
scanout = clutter_stage_view_take_scanout (view);
|
||||
if (scanout)
|
||||
clutter_stage_cogl_scanout_view (stage_cogl, view, scanout);
|
||||
else
|
||||
clutter_stage_cogl_redraw_view_primary (stage_cogl, view);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -812,10 +691,8 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
|
||||
iface->resize = clutter_stage_cogl_resize;
|
||||
iface->show = clutter_stage_cogl_show;
|
||||
iface->hide = clutter_stage_cogl_hide;
|
||||
iface->schedule_update = clutter_stage_cogl_schedule_update;
|
||||
iface->get_update_time = clutter_stage_cogl_get_update_time;
|
||||
iface->clear_update_time = clutter_stage_cogl_clear_update_time;
|
||||
iface->redraw = clutter_stage_cogl_redraw;
|
||||
iface->get_frame_counter = clutter_stage_cogl_get_frame_counter;
|
||||
iface->redraw_view = clutter_stage_cogl_redraw_view;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -856,10 +733,43 @@ _clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
|
||||
static void
|
||||
_clutter_stage_cogl_init (ClutterStageCogl *stage)
|
||||
{
|
||||
stage->last_presentation_time = 0;
|
||||
stage->refresh_rate = 0.0;
|
||||
}
|
||||
|
||||
stage->update_time = -1;
|
||||
static void
|
||||
frame_cb (CoglOnscreen *onscreen,
|
||||
CoglFrameEvent frame_event,
|
||||
CoglFrameInfo *frame_info,
|
||||
void *user_data)
|
||||
{
|
||||
ClutterStageView *view = user_data;
|
||||
ClutterFrameInfo clutter_frame_info;
|
||||
|
||||
if (frame_event == COGL_FRAME_EVENT_SYNC)
|
||||
return;
|
||||
|
||||
clutter_frame_info = (ClutterFrameInfo) {
|
||||
.frame_counter = cogl_frame_info_get_global_frame_counter (frame_info),
|
||||
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info),
|
||||
.presentation_time = ns2us (cogl_frame_info_get_presentation_time (frame_info)),
|
||||
};
|
||||
|
||||
clutter_stage_view_notify_presented (view, &clutter_frame_info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_framebuffer_set (ClutterStageView *view)
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
|
||||
framebuffer = clutter_stage_view_get_onscreen (view);
|
||||
|
||||
if (framebuffer && cogl_is_onscreen (framebuffer))
|
||||
{
|
||||
cogl_onscreen_add_frame_callback (COGL_ONSCREEN (framebuffer),
|
||||
frame_cb,
|
||||
view,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -869,6 +779,7 @@ clutter_stage_view_cogl_finalize (GObject *object)
|
||||
ClutterStageViewCoglPrivate *view_priv =
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
|
||||
g_clear_handle_id (&view_priv->notify_presented_handle_id, g_source_remove);
|
||||
clutter_damage_history_free (view_priv->damage_history);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_view_cogl_parent_class)->finalize (object);
|
||||
@@ -881,6 +792,9 @@ clutter_stage_view_cogl_init (ClutterStageViewCogl *view_cogl)
|
||||
clutter_stage_view_cogl_get_instance_private (view_cogl);
|
||||
|
||||
view_priv->damage_history = clutter_damage_history_new ();
|
||||
|
||||
g_signal_connect (view_cogl, "notify::framebuffer",
|
||||
G_CALLBACK (on_framebuffer_set), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -41,20 +41,6 @@ struct _ClutterStageCogl
|
||||
|
||||
/* back pointer to the backend */
|
||||
ClutterBackend *backend;
|
||||
|
||||
float refresh_rate;
|
||||
int pending_swaps;
|
||||
|
||||
gint64 last_presentation_time;
|
||||
gint64 update_time;
|
||||
int64_t last_update_time;
|
||||
|
||||
/* We only enable clipped redraws after 2 frames, since we've seen
|
||||
* a lot of drivers can struggle to get going and may output some
|
||||
* junk frames to start with. */
|
||||
unsigned int frame_count;
|
||||
|
||||
gint last_sync_delay;
|
||||
};
|
||||
|
||||
struct _ClutterStageCoglClass
|
||||
|
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd
|
||||
* Copyright (C) 2009, 2010 Intel Corp
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_ACTOR_DEPRECATED_H__
|
||||
#define __CLUTTER_ACTOR_DEPRECATED_H__
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
ClutterActor * clutter_get_actor_by_gid (guint32 id_);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_add_child)
|
||||
void clutter_actor_set_parent (ClutterActor *self,
|
||||
ClutterActor *parent);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_remove_child)
|
||||
void clutter_actor_unparent (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_push_internal (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_pop_internal (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_show_all (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_z_position)
|
||||
void clutter_actor_set_depth (ClutterActor *self,
|
||||
gfloat depth);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_z_position)
|
||||
gfloat clutter_actor_get_depth (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_rotation_angle)
|
||||
void clutter_actor_set_rotation (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
gdouble angle,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat z);
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_rotation_angle and clutter_actor_set_pivot_point)
|
||||
void clutter_actor_set_z_rotation_from_gravity (ClutterActor *self,
|
||||
gdouble angle,
|
||||
ClutterGravity gravity);
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_rotation_angle)
|
||||
gdouble clutter_actor_get_rotation (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
gfloat *x,
|
||||
gfloat *y,
|
||||
gfloat *z);
|
||||
CLUTTER_DEPRECATED
|
||||
ClutterGravity clutter_actor_get_z_rotation_gravity (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_scale and clutter_actor_set_pivot_point)
|
||||
void clutter_actor_set_scale_full (ClutterActor *self,
|
||||
gdouble scale_x,
|
||||
gdouble scale_y,
|
||||
gfloat center_x,
|
||||
gfloat center_y);
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_pivot_point)
|
||||
void clutter_actor_get_scale_center (ClutterActor *self,
|
||||
gfloat *center_x,
|
||||
gfloat *center_y);
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_pivot_point)
|
||||
ClutterGravity clutter_actor_get_scale_gravity (ClutterActor *self);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_set_anchor_point (ClutterActor *self,
|
||||
gfloat anchor_x,
|
||||
gfloat anchor_y);
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_move_anchor_point (ClutterActor *self,
|
||||
gfloat anchor_x,
|
||||
gfloat anchor_y);
|
||||
CLUTTER_DEPRECATED
|
||||
ClutterGravity clutter_actor_get_anchor_point_gravity (ClutterActor *self);
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_set_anchor_point_from_gravity (ClutterActor *self,
|
||||
ClutterGravity gravity);
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_actor_move_anchor_point_from_gravity (ClutterActor *self,
|
||||
ClutterGravity gravity);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_ACTOR_DEPRECATED_H__ */
|
@@ -1,745 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009,2010 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-box
|
||||
* @short_description: A Generic layout container
|
||||
*
|
||||
* #ClutterBox is a #ClutterActor sub-class implementing the #ClutterContainer
|
||||
* interface. A Box delegates the whole size requisition and size allocation to
|
||||
* a #ClutterLayoutManager instance.
|
||||
*
|
||||
* #ClutterBox is available since Clutter 1.2
|
||||
*
|
||||
* #ClutterBox is deprecated since Clutter 1.10; all its relevant API is provided
|
||||
* by #ClutterActor, via the #ClutterActor:layout-manager property.
|
||||
*
|
||||
* ## Using ClutterBox
|
||||
*
|
||||
* The following code shows how to create a #ClutterBox with
|
||||
* a #ClutterLayoutManager sub-class, and how to add children to
|
||||
* it via clutter_box_pack().
|
||||
*
|
||||
* |[<!-- language="C" -->
|
||||
* ClutterActor *box;
|
||||
* ClutterLayoutManager *layout;
|
||||
*
|
||||
* // Create the layout manager first
|
||||
* layout = clutter_box_layout_new ();
|
||||
* clutter_box_layout_set_homogeneous (CLUTTER_BOX_LAYOUT (layout), TRUE);
|
||||
* clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12);
|
||||
*
|
||||
* // Then create the ClutterBox actor. The Box will take
|
||||
* // ownership of the ClutterLayoutManager instance by sinking
|
||||
* // its floating reference
|
||||
* box = clutter_box_new (layout);
|
||||
*
|
||||
* // Now add children to the Box using the variadic arguments
|
||||
* // function clutter_box_pack() to set layout properties
|
||||
* clutter_box_pack (CLUTTER_BOX (box), actor,
|
||||
* "x-align", CLUTTER_BOX_ALIGNMENT_CENTER,
|
||||
* "y-align", CLUTTER_BOX_ALIGNMENT_END,
|
||||
* "expand", TRUE,
|
||||
* NULL);
|
||||
* ]|
|
||||
*
|
||||
* #ClutterBox's clutter_box_pack() wraps the generic
|
||||
* clutter_container_add_actor() function, but it also allows setting
|
||||
* layout properties while adding the new child to the box.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include "deprecated/clutter-container.h"
|
||||
|
||||
#include "clutter-box.h"
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
struct _ClutterBoxPrivate
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
|
||||
guint changed_id;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_COLOR,
|
||||
PROP_COLOR_SET,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST] = { NULL, };
|
||||
|
||||
static const ClutterColor default_box_color = { 255, 255, 255, 255 };
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBox, clutter_box, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
static inline void
|
||||
clutter_box_set_color_internal (ClutterBox *box,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (box), color);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR_SET]);
|
||||
g_object_notify_by_pspec (G_OBJECT (box), obj_props[PROP_COLOR]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_box_real_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
gboolean retval = FALSE;
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
|
||||
/* if we have a background color, and an allocation, then we need to
|
||||
* set it as the base of our paint volume
|
||||
*/
|
||||
retval = clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
|
||||
/* bail out early if we don't have any child */
|
||||
if (clutter_actor_get_n_children (actor) == 0)
|
||||
return retval;
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
/* otherwise, union the paint volumes of our children, in case
|
||||
* any one of them decides to paint outside the parent's allocation
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
const ClutterPaintVolume *child_volume;
|
||||
|
||||
/* This gets the paint volume of the child transformed into the
|
||||
* group's coordinate space... */
|
||||
child_volume = clutter_actor_get_transformed_paint_volume (child, actor);
|
||||
if (!child_volume)
|
||||
return FALSE;
|
||||
|
||||
clutter_paint_volume_union (volume, child_volume);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBox *self = CLUTTER_BOX (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR:
|
||||
clutter_box_set_color_internal (self, clutter_value_get_color (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR:
|
||||
{
|
||||
ClutterColor color;
|
||||
|
||||
clutter_actor_get_background_color (CLUTTER_ACTOR (gobject),
|
||||
&color);
|
||||
clutter_value_set_color (value, &color);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_COLOR_SET:
|
||||
{
|
||||
gboolean color_set;
|
||||
|
||||
g_object_get (gobject, "background-color-set", &color_set, NULL);
|
||||
g_value_set_boolean (value, color_set);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_destroy (ClutterActor *actor)
|
||||
{
|
||||
ClutterActor *iter;
|
||||
|
||||
iter = clutter_actor_get_first_child (actor);
|
||||
while (iter != NULL)
|
||||
{
|
||||
ClutterActor *next = clutter_actor_get_next_sibling (iter);
|
||||
|
||||
clutter_actor_destroy (iter);
|
||||
|
||||
iter = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_class_init (ClutterBoxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->destroy = clutter_box_real_destroy;
|
||||
actor_class->get_paint_volume = clutter_box_real_get_paint_volume;
|
||||
|
||||
gobject_class->set_property = clutter_box_set_property;
|
||||
gobject_class->get_property = clutter_box_get_property;
|
||||
|
||||
/**
|
||||
* ClutterBox:color:
|
||||
*
|
||||
* The color to be used to paint the background of the
|
||||
* #ClutterBox. Setting this property will set the
|
||||
* #ClutterBox:color-set property as a side effect
|
||||
*
|
||||
* This property sets the #ClutterActor:background-color property
|
||||
* internally.
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use the #ClutterActor:background-color property
|
||||
*/
|
||||
obj_props[PROP_COLOR] =
|
||||
clutter_param_spec_color ("color",
|
||||
P_("Color"),
|
||||
P_("The background color of the box"),
|
||||
&default_box_color,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
|
||||
/**
|
||||
* ClutterBox:color-set:
|
||||
*
|
||||
* Whether the #ClutterBox:color property has been set.
|
||||
*
|
||||
* This property reads the #ClutterActor:background-color-set property
|
||||
* internally.
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use the #ClutterActor:background-color-set property
|
||||
*/
|
||||
obj_props[PROP_COLOR_SET] =
|
||||
g_param_spec_boolean ("color-set",
|
||||
P_("Color Set"),
|
||||
P_("Whether the background color is set"),
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_init (ClutterBox *self)
|
||||
{
|
||||
self->priv = clutter_box_get_instance_private (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_new:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
*
|
||||
* Creates a new #ClutterBox. The children of the box will be layed
|
||||
* out by the passed @manager
|
||||
*
|
||||
* Return value: the newly created #ClutterBox actor
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_new() instead.
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_box_new (ClutterLayoutManager *manager)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL);
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_BOX,
|
||||
"layout-manager", manager,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_set_layout_manager:
|
||||
* @box: a #ClutterBox
|
||||
* @manager: a #ClutterLayoutManager
|
||||
*
|
||||
* Sets the #ClutterLayoutManager for @box
|
||||
*
|
||||
* A #ClutterLayoutManager is a delegate object that controls the
|
||||
* layout of the children of @box
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_set_layout_manager() instead.
|
||||
*/
|
||||
void
|
||||
clutter_box_set_layout_manager (ClutterBox *box,
|
||||
ClutterLayoutManager *manager)
|
||||
{
|
||||
clutter_actor_set_layout_manager (CLUTTER_ACTOR (box), manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_get_layout_manager:
|
||||
* @box: a #ClutterBox
|
||||
*
|
||||
* Retrieves the #ClutterLayoutManager instance used by @box
|
||||
*
|
||||
* Return value: (transfer none): a #ClutterLayoutManager. The returned
|
||||
* #ClutterLayoutManager is owned by the #ClutterBox and it should not
|
||||
* be unreferenced
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_get_layout_manager() instead.
|
||||
*/
|
||||
ClutterLayoutManager *
|
||||
clutter_box_get_layout_manager (ClutterBox *box)
|
||||
{
|
||||
return clutter_actor_get_layout_manager (CLUTTER_ACTOR (box));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_packv:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @n_properties: the number of properties to set
|
||||
* @properties: (array length=n_properties) (element-type utf8): a vector
|
||||
* containing the property names to set
|
||||
* @values: (array length=n_properties): a vector containing the property
|
||||
* values to set
|
||||
*
|
||||
* Vector-based variant of clutter_box_pack(), intended for language
|
||||
* bindings to use
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_add_child() instead. To set
|
||||
* specific layout properties, use clutter_layout_manager_child_set()
|
||||
*/
|
||||
void
|
||||
clutter_box_packv (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
guint n_properties,
|
||||
const gchar * const properties[],
|
||||
const GValue *values)
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterContainer *container;
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
container = CLUTTER_CONTAINER (box);
|
||||
clutter_container_add_actor (container, actor);
|
||||
|
||||
manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box));
|
||||
if (manager == NULL)
|
||||
return;
|
||||
|
||||
meta = clutter_layout_manager_get_child_meta (manager,
|
||||
container,
|
||||
actor);
|
||||
|
||||
if (meta == NULL)
|
||||
return;
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
for (i = 0; i < n_properties; i++)
|
||||
{
|
||||
const gchar *pname = properties[i];
|
||||
GParamSpec *pspec;
|
||||
|
||||
pspec = g_object_class_find_property (klass, pname);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') does not exist",
|
||||
G_STRLOC,
|
||||
pname,
|
||||
G_OBJECT_TYPE_NAME (manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') is not writable",
|
||||
G_STRLOC,
|
||||
pspec->name,
|
||||
G_OBJECT_TYPE_NAME (manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_layout_manager_child_set_property (manager,
|
||||
container, actor,
|
||||
pname, &values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_box_set_property_valist (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
va_list var_args)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (box);
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
const gchar *pname;
|
||||
|
||||
manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (box));
|
||||
if (manager == NULL)
|
||||
return;
|
||||
|
||||
meta = clutter_layout_manager_get_child_meta (manager,
|
||||
container,
|
||||
actor);
|
||||
|
||||
if (meta == NULL)
|
||||
return;
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
pname = first_property;
|
||||
while (pname)
|
||||
{
|
||||
GValue value = { 0, };
|
||||
GParamSpec *pspec;
|
||||
gchar *error;
|
||||
|
||||
pspec = g_object_class_find_property (klass, pname);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') does not exist",
|
||||
G_STRLOC,
|
||||
pname,
|
||||
G_OBJECT_TYPE_NAME (manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') is not writable",
|
||||
G_STRLOC,
|
||||
pspec->name,
|
||||
G_OBJECT_TYPE_NAME (manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec),
|
||||
var_args, 0,
|
||||
&error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_layout_manager_child_set_property (manager,
|
||||
container, actor,
|
||||
pspec->name, &value);
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
pname = va_arg (var_args, gchar*);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_pack:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @first_property: the name of the first property to set, or %NULL
|
||||
* @...: a list of property name and value pairs, terminated by %NULL
|
||||
*
|
||||
* Adds @actor to @box and sets layout properties at the same time,
|
||||
* if the #ClutterLayoutManager used by @box has them
|
||||
*
|
||||
* This function is a wrapper around clutter_container_add_actor()
|
||||
* and clutter_layout_manager_child_set()
|
||||
*
|
||||
* Language bindings should use the vector-based clutter_box_packv()
|
||||
* variant instead
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_add_child() instead. To set
|
||||
* specific layout properties, use clutter_layout_manager_child_set()
|
||||
*/
|
||||
void
|
||||
clutter_box_pack (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (box), actor);
|
||||
|
||||
if (first_property == NULL || *first_property == '\0')
|
||||
return;
|
||||
|
||||
va_start (var_args, first_property);
|
||||
clutter_box_set_property_valist (box, actor, first_property, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_pack_after:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @sibling: (allow-none): a #ClutterActor or %NULL
|
||||
* @first_property: the name of the first property to set, or %NULL
|
||||
* @...: a list of property name and value pairs, terminated by %NULL
|
||||
*
|
||||
* Adds @actor to @box, placing it after @sibling, and sets layout
|
||||
* properties at the same time, if the #ClutterLayoutManager used by
|
||||
* @box supports them
|
||||
*
|
||||
* If @sibling is %NULL then @actor is placed at the end of the
|
||||
* list of children, to be allocated and painted after every other child
|
||||
*
|
||||
* This function is a wrapper around clutter_container_add_actor(),
|
||||
* clutter_container_raise_child() and clutter_layout_manager_child_set()
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_insert_child_above() instead.
|
||||
* To set specific layout properties, use clutter_layout_manager_child_set()
|
||||
*/
|
||||
void
|
||||
clutter_box_pack_after (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (box), actor);
|
||||
clutter_container_raise_child (CLUTTER_CONTAINER (box), actor, sibling);
|
||||
|
||||
if (first_property == NULL || *first_property == '\0')
|
||||
return;
|
||||
|
||||
va_start (var_args, first_property);
|
||||
clutter_box_set_property_valist (box, actor, first_property, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_pack_before:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @sibling: (allow-none): a #ClutterActor or %NULL
|
||||
* @first_property: the name of the first property to set, or %NULL
|
||||
* @...: a list of property name and value pairs, terminated by %NULL
|
||||
*
|
||||
* Adds @actor to @box, placing it before @sibling, and sets layout
|
||||
* properties at the same time, if the #ClutterLayoutManager used by
|
||||
* @box supports them
|
||||
*
|
||||
* If @sibling is %NULL then @actor is placed at the beginning of the
|
||||
* list of children, to be allocated and painted below every other child
|
||||
*
|
||||
* This function is a wrapper around clutter_container_add_actor(),
|
||||
* clutter_container_lower_child() and clutter_layout_manager_child_set()
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_insert_child_below() instead.
|
||||
* To set specific layout properties, use clutter_layout_manager_child_set()
|
||||
*/
|
||||
void
|
||||
clutter_box_pack_before (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling));
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (box), actor);
|
||||
clutter_container_lower_child (CLUTTER_CONTAINER (box), actor, sibling);
|
||||
|
||||
if (first_property == NULL || *first_property == '\0')
|
||||
return;
|
||||
|
||||
va_start (var_args, first_property);
|
||||
clutter_box_set_property_valist (box, actor, first_property, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_pack_at:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @position: the position to insert the @actor at
|
||||
* @first_property: the name of the first property to set, or %NULL
|
||||
* @...: a list of property name and value pairs, terminated by %NULL
|
||||
*
|
||||
* Adds @actor to @box, placing it at @position, and sets layout
|
||||
* properties at the same time, if the #ClutterLayoutManager used by
|
||||
* @box supports them
|
||||
*
|
||||
* If @position is a negative number, or is larger than the number of
|
||||
* children of @box, the new child is added at the end of the list of
|
||||
* children
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_insert_child_at_index() instead.
|
||||
* To set specific layout properties, use clutter_layout_manager_child_set()
|
||||
*/
|
||||
void
|
||||
clutter_box_pack_at (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
gint position,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
clutter_actor_insert_child_at_index (CLUTTER_ACTOR (box),
|
||||
actor,
|
||||
position);
|
||||
|
||||
/* we need to explicitly call this, because we're not going through
|
||||
* the default code paths provided by clutter_container_add()
|
||||
*/
|
||||
clutter_container_create_child_meta (CLUTTER_CONTAINER (box), actor);
|
||||
|
||||
g_signal_emit_by_name (box, "actor-added", actor);
|
||||
|
||||
if (first_property == NULL || *first_property == '\0')
|
||||
return;
|
||||
|
||||
va_start (var_args, first_property);
|
||||
clutter_box_set_property_valist (box, actor, first_property, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_set_color:
|
||||
* @box: a #ClutterBox
|
||||
* @color: (allow-none): the background color, or %NULL to unset
|
||||
*
|
||||
* Sets (or unsets) the background color for @box
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_set_background_color() instead.
|
||||
*/
|
||||
void
|
||||
clutter_box_set_color (ClutterBox *box,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
|
||||
clutter_box_set_color_internal (box, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_get_color:
|
||||
* @box: a #ClutterBox
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
*
|
||||
* Retrieves the background color of @box
|
||||
*
|
||||
* If the #ClutterBox:color-set property is set to %FALSE the
|
||||
* returned #ClutterColor is undefined
|
||||
*
|
||||
* Since: 1.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_get_background_color() instead.
|
||||
*/
|
||||
void
|
||||
clutter_box_get_color (ClutterBox *box,
|
||||
ClutterColor *color)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
clutter_actor_get_background_color (CLUTTER_ACTOR (box), color);
|
||||
}
|
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009,2010 Intel Corporation.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_BOX_H__
|
||||
#define __CLUTTER_BOX_H__
|
||||
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-container.h>
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BOX (clutter_box_get_type ())
|
||||
#define CLUTTER_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX, ClutterBox))
|
||||
#define CLUTTER_IS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX))
|
||||
#define CLUTTER_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX, ClutterBoxClass))
|
||||
#define CLUTTER_IS_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX))
|
||||
#define CLUTTER_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX, ClutterBoxClass))
|
||||
|
||||
typedef struct _ClutterBox ClutterBox;
|
||||
typedef struct _ClutterBoxPrivate ClutterBoxPrivate;
|
||||
typedef struct _ClutterBoxClass ClutterBoxClass;
|
||||
|
||||
/**
|
||||
* ClutterBox:
|
||||
*
|
||||
* The #ClutterBox structure contains only private data and should
|
||||
* be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterBox
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterBoxPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterBoxClass:
|
||||
*
|
||||
* The #ClutterBoxClass structure contains only private data
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterBoxClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding, for future expansion */
|
||||
void (*clutter_padding_1) (void);
|
||||
void (*clutter_padding_2) (void);
|
||||
void (*clutter_padding_3) (void);
|
||||
void (*clutter_padding_4) (void);
|
||||
void (*clutter_padding_5) (void);
|
||||
void (*clutter_padding_6) (void);
|
||||
};
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
GType clutter_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
|
||||
ClutterActor * clutter_box_new (ClutterLayoutManager *manager);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_layout_manager)
|
||||
void clutter_box_set_layout_manager (ClutterBox *box,
|
||||
ClutterLayoutManager *manager);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_layout_manager)
|
||||
ClutterLayoutManager *clutter_box_get_layout_manager (ClutterBox *box);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
|
||||
void clutter_box_set_color (ClutterBox *box,
|
||||
const ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color)
|
||||
void clutter_box_get_color (ClutterBox *box,
|
||||
ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_add_child)
|
||||
void clutter_box_pack (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_add_child)
|
||||
void clutter_box_packv (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
guint n_properties,
|
||||
const gchar * const properties[],
|
||||
const GValue *values);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_above)
|
||||
void clutter_box_pack_after (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling,
|
||||
const gchar *first_property,
|
||||
...);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_below)
|
||||
void clutter_box_pack_before (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling,
|
||||
const gchar *first_property,
|
||||
...);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_insert_child_at_index)
|
||||
void clutter_box_pack_at (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
gint position,
|
||||
const gchar *first_property,
|
||||
...);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BOX_H__ */
|
@@ -1,554 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-group
|
||||
* @short_description: A fixed layout container
|
||||
*
|
||||
* A #ClutterGroup is an Actor which contains multiple child actors positioned
|
||||
* relative to the #ClutterGroup position. Other operations such as scaling,
|
||||
* rotating and clipping of the group will apply to the child actors.
|
||||
*
|
||||
* A #ClutterGroup's size is defined by the size and position of its children;
|
||||
* it will be the smallest non-negative size that covers the right and bottom
|
||||
* edges of all of its children.
|
||||
*
|
||||
* Setting the size on a Group using #ClutterActor methods like
|
||||
* clutter_actor_set_size() will override the natural size of the Group,
|
||||
* however this will not affect the size of the children and they may still
|
||||
* be painted outside of the allocation of the group. One way to constrain
|
||||
* the visible area of a #ClutterGroup to a specified allocation is to
|
||||
* explicitly set the size of the #ClutterGroup and then use the
|
||||
* #ClutterActor:clip-to-allocation property.
|
||||
*
|
||||
* #ClutterGroup as a concrete class has been superceded by #ClutterActor
|
||||
* since Clutter 1.10. The type itself is not deprecated as it is used by
|
||||
* #ClutterStage. You should instantiate #ClutterActor and use its API to
|
||||
* manage child actors.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include "clutter-group.h"
|
||||
|
||||
#include "clutter-actor.h"
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-container.h"
|
||||
#include "clutter-fixed-layout.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
struct _ClutterGroupPrivate
|
||||
{
|
||||
GList *children;
|
||||
|
||||
ClutterLayoutManager *layout;
|
||||
};
|
||||
|
||||
static void clutter_container_iface_init (ClutterContainerIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterGroup, clutter_group, CLUTTER_TYPE_ACTOR,
|
||||
G_ADD_PRIVATE (ClutterGroup)
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||
clutter_container_iface_init));
|
||||
|
||||
static gint
|
||||
sort_by_depth (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
gfloat depth_a = clutter_actor_get_depth (CLUTTER_ACTOR(a));
|
||||
gfloat depth_b = clutter_actor_get_depth (CLUTTER_ACTOR(b));
|
||||
|
||||
if (depth_a < depth_b)
|
||||
return -1;
|
||||
|
||||
if (depth_a > depth_b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_add (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
|
||||
|
||||
g_object_ref (actor);
|
||||
|
||||
priv->children = g_list_append (priv->children, actor);
|
||||
clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
|
||||
|
||||
g_signal_emit_by_name (container, "actor-added", actor);
|
||||
|
||||
clutter_container_sort_depth_order (container);
|
||||
|
||||
g_object_unref (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_actor_added (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
|
||||
|
||||
/* XXX - children added using clutter_actor_add_child() will
|
||||
* cause actor-added to be emitted without going through the
|
||||
* add() virtual function.
|
||||
*
|
||||
* if we get an actor-added for a child that is not in our
|
||||
* list of children already, then we go in compatibility
|
||||
* mode.
|
||||
*/
|
||||
if (g_list_find (priv->children, actor) != NULL)
|
||||
return;
|
||||
|
||||
priv->children = g_list_append (priv->children, actor);
|
||||
clutter_container_sort_depth_order (container);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_remove (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
|
||||
|
||||
g_object_ref (actor);
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
clutter_actor_unparent (actor);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
|
||||
|
||||
g_signal_emit_by_name (container, "actor-removed", actor);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
|
||||
g_object_unref (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_actor_removed (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
|
||||
|
||||
/* XXX - same compatibility mode of the ::actor-added implementation */
|
||||
if (g_list_find (priv->children, actor) == NULL)
|
||||
return;
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_raise (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
|
||||
/* Raise at the top */
|
||||
if (!sibling)
|
||||
{
|
||||
GList *last_item;
|
||||
|
||||
last_item = g_list_last (priv->children);
|
||||
|
||||
if (last_item)
|
||||
sibling = last_item->data;
|
||||
|
||||
priv->children = g_list_append (priv->children, actor);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint index_ = g_list_index (priv->children, sibling) + 1;
|
||||
|
||||
priv->children = g_list_insert (priv->children, actor, index_);
|
||||
}
|
||||
|
||||
/* set Z ordering a value below, this will then call sort
|
||||
* as values are equal ordering shouldn't change but Z
|
||||
* values will be correct.
|
||||
*
|
||||
* FIXME: get rid of this crap; this is so utterly broken and wrong on
|
||||
* so many levels it's not even funny. sadly, we get to keep this until
|
||||
* we can break API and remove Group for good.
|
||||
*/
|
||||
if (sibling &&
|
||||
clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor))
|
||||
{
|
||||
clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling));
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_lower (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling)
|
||||
{
|
||||
ClutterGroup *self = CLUTTER_GROUP (container);
|
||||
ClutterGroupPrivate *priv = self->priv;
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
|
||||
/* Push to bottom */
|
||||
if (!sibling)
|
||||
{
|
||||
GList *last_item;
|
||||
|
||||
last_item = g_list_first (priv->children);
|
||||
|
||||
if (last_item)
|
||||
sibling = last_item->data;
|
||||
|
||||
priv->children = g_list_prepend (priv->children, actor);
|
||||
}
|
||||
else
|
||||
{
|
||||
gint index_ = g_list_index (priv->children, sibling);
|
||||
|
||||
priv->children = g_list_insert (priv->children, actor, index_);
|
||||
}
|
||||
|
||||
/* See comment in group_raise for this */
|
||||
if (sibling &&
|
||||
clutter_actor_get_depth (sibling) != clutter_actor_get_depth (actor))
|
||||
{
|
||||
clutter_actor_set_depth (actor, clutter_actor_get_depth (sibling));
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_sort_depth_order (ClutterContainer *container)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (container)->priv;
|
||||
|
||||
priv->children = g_list_sort (priv->children, sort_by_depth);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_container_iface_init (ClutterContainerIface *iface)
|
||||
{
|
||||
iface->add = clutter_group_real_add;
|
||||
iface->actor_added = clutter_group_real_actor_added;
|
||||
iface->remove = clutter_group_real_remove;
|
||||
iface->actor_removed = clutter_group_real_actor_removed;
|
||||
iface->raise = clutter_group_real_raise;
|
||||
iface->lower = clutter_group_real_lower;
|
||||
iface->sort_depth_order = clutter_group_real_sort_depth_order;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_paint (ClutterActor *actor,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
|
||||
CLUTTER_NOTE (PAINT, "ClutterGroup paint enter '%s'",
|
||||
_clutter_actor_get_debug_name (actor));
|
||||
|
||||
g_list_foreach (priv->children, (GFunc) clutter_actor_paint, paint_context);
|
||||
|
||||
CLUTTER_NOTE (PAINT, "ClutterGroup paint leave '%s'",
|
||||
_clutter_actor_get_debug_name (actor));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_pick (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
|
||||
/* Chain up so we get a bounding box pained (if we are reactive) */
|
||||
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, pick_context);
|
||||
|
||||
g_list_foreach (priv->children, (GFunc) clutter_actor_pick, pick_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_get_preferred_width (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width,
|
||||
gfloat *natural_width)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
|
||||
clutter_layout_manager_get_preferred_width (priv->layout,
|
||||
CLUTTER_CONTAINER (actor),
|
||||
for_height,
|
||||
min_width, natural_width);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_get_preferred_height (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
gfloat *min_height,
|
||||
gfloat *natural_height)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
|
||||
clutter_layout_manager_get_preferred_height (priv->layout,
|
||||
CLUTTER_CONTAINER (actor),
|
||||
for_width,
|
||||
min_height, natural_height);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_allocate (ClutterActor *actor,
|
||||
const ClutterActorBox *allocation)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
ClutterActorClass *klass;
|
||||
|
||||
klass = CLUTTER_ACTOR_CLASS (clutter_group_parent_class);
|
||||
klass->allocate (actor, allocation);
|
||||
|
||||
if (priv->children == NULL)
|
||||
return;
|
||||
|
||||
clutter_layout_manager_allocate (priv->layout,
|
||||
CLUTTER_CONTAINER (actor),
|
||||
allocation);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_dispose (GObject *object)
|
||||
{
|
||||
ClutterGroup *self = CLUTTER_GROUP (object);
|
||||
ClutterGroupPrivate *priv = self->priv;
|
||||
|
||||
/* Note: we are careful to consider that destroying children could
|
||||
* have the side-effect of destroying other children so
|
||||
* priv->children may be modified during clutter_actor_destroy. */
|
||||
while (priv->children != NULL)
|
||||
{
|
||||
ClutterActor *child = priv->children->data;
|
||||
priv->children = g_list_delete_link (priv->children, priv->children);
|
||||
clutter_actor_destroy (child);
|
||||
}
|
||||
|
||||
if (priv->layout)
|
||||
{
|
||||
clutter_layout_manager_set_container (priv->layout, NULL);
|
||||
g_object_unref (priv->layout);
|
||||
priv->layout = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_show_all (ClutterActor *self)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *actor;
|
||||
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &actor))
|
||||
clutter_actor_show (actor);
|
||||
|
||||
clutter_actor_show (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_real_hide_all (ClutterActor *actor)
|
||||
{
|
||||
ClutterActorIter iter;
|
||||
|
||||
clutter_actor_hide (actor);
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &actor))
|
||||
clutter_actor_hide (actor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_group_real_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
GList *l;
|
||||
|
||||
if (priv->children == NULL)
|
||||
return TRUE;
|
||||
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
const ClutterPaintVolume *child_volume;
|
||||
|
||||
/* This gets the paint volume of the child transformed into the
|
||||
* group's coordinate space... */
|
||||
child_volume = clutter_actor_get_transformed_paint_volume (child, actor);
|
||||
if (!child_volume)
|
||||
return FALSE;
|
||||
|
||||
clutter_paint_volume_union (volume, child_volume);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_class_init (ClutterGroupClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
actor_class->get_preferred_width = clutter_group_real_get_preferred_width;
|
||||
actor_class->get_preferred_height = clutter_group_real_get_preferred_height;
|
||||
actor_class->allocate = clutter_group_real_allocate;
|
||||
actor_class->paint = clutter_group_real_paint;
|
||||
actor_class->pick = clutter_group_real_pick;
|
||||
actor_class->show_all = clutter_group_real_show_all;
|
||||
actor_class->hide_all = clutter_group_real_hide_all;
|
||||
actor_class->get_paint_volume = clutter_group_real_get_paint_volume;
|
||||
|
||||
gobject_class->dispose = clutter_group_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_init (ClutterGroup *self)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (self);
|
||||
|
||||
self->priv = clutter_group_get_instance_private (self);
|
||||
|
||||
/* turn on some optimization
|
||||
*
|
||||
* XXX - these so-called "optimizations" are insane and should have never
|
||||
* been used. they introduce some weird behaviour that breaks invariants
|
||||
* and have to be explicitly worked around.
|
||||
*
|
||||
* this flag was set by the ClutterFixedLayout, but since that layout
|
||||
* manager is now the default for ClutterActor, we set the flag explicitly
|
||||
* here, to avoid breaking perfectly working actors overriding the
|
||||
* allocate() virtual function.
|
||||
*
|
||||
* also, we keep this flag here so that it can die once we get rid of
|
||||
* ClutterGroup.
|
||||
*/
|
||||
clutter_actor_set_flags (actor, CLUTTER_ACTOR_NO_LAYOUT);
|
||||
|
||||
self->priv->layout = clutter_fixed_layout_new ();
|
||||
g_object_ref_sink (self->priv->layout);
|
||||
|
||||
clutter_actor_set_layout_manager (actor, self->priv->layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_group_new:
|
||||
*
|
||||
* Create a new #ClutterGroup.
|
||||
*
|
||||
* Return value: the newly created #ClutterGroup actor
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_new() instead.
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_group_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_GROUP, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_group_remove_all:
|
||||
* @self: A #ClutterGroup
|
||||
*
|
||||
* Removes all children actors from the #ClutterGroup.
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_remove_all_children() instead.
|
||||
*/
|
||||
void
|
||||
clutter_group_remove_all (ClutterGroup *self)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_GROUP (self));
|
||||
|
||||
clutter_actor_remove_all_children (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_group_get_n_children:
|
||||
* @self: A #ClutterGroup
|
||||
*
|
||||
* Gets the number of actors held in the group.
|
||||
*
|
||||
* Return value: The number of child actors held in the group.
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_get_n_children() instead.
|
||||
*/
|
||||
gint
|
||||
clutter_group_get_n_children (ClutterGroup *self)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_GROUP (self), 0);
|
||||
|
||||
return clutter_actor_get_n_children (CLUTTER_ACTOR (self));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_group_get_nth_child:
|
||||
* @self: A #ClutterGroup
|
||||
* @index_: the position of the requested actor.
|
||||
*
|
||||
* Gets a groups child held at @index_ in stack.
|
||||
*
|
||||
* Return value: (transfer none): A Clutter actor, or %NULL if
|
||||
* @index_ is invalid.
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_get_child_at_index() instead.
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_group_get_nth_child (ClutterGroup *self,
|
||||
gint index_)
|
||||
{
|
||||
ClutterActor *actor;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_GROUP (self), NULL);
|
||||
|
||||
actor = CLUTTER_ACTOR (self);
|
||||
g_return_val_if_fail (index_ <= clutter_actor_get_n_children (actor), NULL);
|
||||
|
||||
return clutter_actor_get_child_at_index (actor, index_);
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corp
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_GROUP_DEPRECATED_H__
|
||||
#define __CLUTTER_GROUP_DEPRECATED_H__
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-group.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
|
||||
ClutterActor * clutter_group_new (void);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_child_at_index)
|
||||
ClutterActor * clutter_group_get_nth_child (ClutterGroup *self,
|
||||
gint index_);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_n_children)
|
||||
gint clutter_group_get_n_children (ClutterGroup *self);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_remove_all_children)
|
||||
void clutter_group_remove_all (ClutterGroup *self);
|
||||
|
||||
#ifndef CLUTTER_DISABLE_DEPRECATED
|
||||
|
||||
/* for Mr. Mallum only */
|
||||
#define clutter_group_add(group,actor) G_STMT_START { \
|
||||
ClutterActor *_actor = (ClutterActor *) (actor); \
|
||||
if (CLUTTER_IS_GROUP ((group)) && CLUTTER_IS_ACTOR ((_actor))) \
|
||||
{ \
|
||||
ClutterContainer *_container = (ClutterContainer *) (group); \
|
||||
clutter_container_add_actor (_container, _actor); \
|
||||
} } G_STMT_END
|
||||
|
||||
#endif /* CLUTTER_DISABLE_DEPRECATED */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_GROUP_DEPRECATED_H__ */
|
@@ -1,626 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-rectangle
|
||||
* @short_description: An actor that displays a simple rectangle.
|
||||
*
|
||||
* #ClutterRectangle is a #ClutterActor which draws a simple filled rectangle.
|
||||
*
|
||||
* #ClutterRectangle is deprecated since Clutter 1.10. If you want an actor
|
||||
* painting a solid color, you can replace it with #ClutterActor and set the
|
||||
* #ClutterActor:background-color property to the desired #ClutterColor. If
|
||||
* you are drawing more complex shapes, use #ClutterCanvas to draw using the
|
||||
* Cairo 2D API instead.
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
|
||||
#include "deprecated/clutter-rectangle.h"
|
||||
#include "deprecated/clutter-actor.h"
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
struct _ClutterRectanglePrivate
|
||||
{
|
||||
ClutterColor color;
|
||||
ClutterColor border_color;
|
||||
|
||||
guint border_width;
|
||||
|
||||
guint has_border : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_COLOR,
|
||||
PROP_BORDER_COLOR,
|
||||
PROP_BORDER_WIDTH,
|
||||
PROP_HAS_BORDER
|
||||
|
||||
/* FIXME: Add gradient, rounded corner props etc */
|
||||
};
|
||||
|
||||
static const ClutterColor default_color = { 255, 255, 255, 255 };
|
||||
static const ClutterColor default_border_color = { 0, 0, 0, 255 };
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterRectangle, clutter_rectangle, CLUTTER_TYPE_ACTOR)
|
||||
|
||||
static void
|
||||
clutter_rectangle_paint (ClutterActor *self,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE (self)->priv;
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_paint_context_get_framebuffer (paint_context);
|
||||
static CoglPipeline *default_color_pipeline = NULL;
|
||||
CoglPipeline *content_pipeline;
|
||||
ClutterActorBox alloc;
|
||||
CoglColor color;
|
||||
guint8 tmp_alpha;
|
||||
|
||||
CLUTTER_NOTE (PAINT,
|
||||
"painting rect '%s'",
|
||||
clutter_actor_get_name (self) ? clutter_actor_get_name (self)
|
||||
: "unknown");
|
||||
clutter_actor_get_allocation_box (self, &alloc);
|
||||
|
||||
if (G_UNLIKELY (default_color_pipeline == NULL))
|
||||
{
|
||||
CoglContext *ctx =
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
default_color_pipeline = cogl_pipeline_new (ctx);
|
||||
}
|
||||
|
||||
g_assert (default_color_pipeline != NULL);
|
||||
content_pipeline = cogl_pipeline_copy (default_color_pipeline);
|
||||
|
||||
/* compute the composited opacity of the actor taking into
|
||||
* account the opacity of the color set by the user
|
||||
*/
|
||||
tmp_alpha = clutter_actor_get_paint_opacity (self)
|
||||
* priv->color.alpha
|
||||
/ 255;
|
||||
|
||||
cogl_color_init_from_4ub (&color,
|
||||
priv->color.red,
|
||||
priv->color.green,
|
||||
priv->color.blue,
|
||||
tmp_alpha);
|
||||
cogl_color_premultiply (&color);
|
||||
cogl_pipeline_set_color (content_pipeline, &color);
|
||||
|
||||
if (priv->has_border)
|
||||
{
|
||||
CoglPipeline *border_pipeline;
|
||||
|
||||
border_pipeline = cogl_pipeline_copy (default_color_pipeline);
|
||||
|
||||
tmp_alpha = clutter_actor_get_paint_opacity (self)
|
||||
* priv->border_color.alpha
|
||||
/ 255;
|
||||
|
||||
cogl_color_init_from_4ub (&color,
|
||||
priv->border_color.red,
|
||||
priv->border_color.green,
|
||||
priv->border_color.blue,
|
||||
tmp_alpha);
|
||||
cogl_color_premultiply (&color);
|
||||
cogl_pipeline_set_color (border_pipeline, &color);
|
||||
|
||||
/* We paint the border and the content only if the rectangle
|
||||
* is big enough to show them
|
||||
*/
|
||||
if ((priv->border_width * 2) < clutter_actor_box_get_width (&alloc) &&
|
||||
(priv->border_width * 2) < clutter_actor_box_get_height (&alloc))
|
||||
{
|
||||
/* paint the border. this sucks, but it's the only way to make a border */
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
border_pipeline,
|
||||
priv->border_width, 0,
|
||||
clutter_actor_box_get_width (&alloc),
|
||||
priv->border_width);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
border_pipeline,
|
||||
clutter_actor_box_get_width (&alloc) - priv->border_width,
|
||||
priv->border_width,
|
||||
clutter_actor_box_get_width (&alloc),
|
||||
clutter_actor_box_get_height (&alloc));
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
border_pipeline,
|
||||
0, clutter_actor_box_get_height (&alloc) - priv->border_width,
|
||||
clutter_actor_box_get_width (&alloc) - priv->border_width,
|
||||
clutter_actor_box_get_height (&alloc));
|
||||
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
border_pipeline,
|
||||
0, 0,
|
||||
priv->border_width,
|
||||
clutter_actor_box_get_height (&alloc) - priv->border_width);
|
||||
|
||||
/* now paint the rectangle */
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
content_pipeline,
|
||||
priv->border_width, priv->border_width,
|
||||
clutter_actor_box_get_width (&alloc) - priv->border_width,
|
||||
clutter_actor_box_get_height (&alloc) - priv->border_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we draw a rectangle with the same color
|
||||
* as the border, since we can only fit that into the
|
||||
* allocation.
|
||||
*/
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
border_pipeline,
|
||||
0, 0,
|
||||
clutter_actor_box_get_width (&alloc),
|
||||
clutter_actor_box_get_height (&alloc));
|
||||
}
|
||||
|
||||
cogl_object_unref (border_pipeline);
|
||||
}
|
||||
else
|
||||
{
|
||||
cogl_framebuffer_draw_rectangle (framebuffer,
|
||||
content_pipeline,
|
||||
0, 0,
|
||||
clutter_actor_box_get_width (&alloc),
|
||||
clutter_actor_box_get_height (&alloc));
|
||||
}
|
||||
|
||||
cogl_object_unref (content_pipeline);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_rectangle_get_paint_volume (ClutterActor *self,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return _clutter_actor_set_default_paint_volume (self,
|
||||
CLUTTER_TYPE_RECTANGLE,
|
||||
volume);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_rectangle_has_overlaps (ClutterActor *self)
|
||||
{
|
||||
/* Rectangles never need an offscreen redirect because there are
|
||||
never any overlapping primitives */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_rectangle_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterRectangle *rectangle = CLUTTER_RECTANGLE(object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR:
|
||||
clutter_rectangle_set_color (rectangle, clutter_value_get_color (value));
|
||||
break;
|
||||
case PROP_BORDER_COLOR:
|
||||
clutter_rectangle_set_border_color (rectangle,
|
||||
clutter_value_get_color (value));
|
||||
break;
|
||||
case PROP_BORDER_WIDTH:
|
||||
clutter_rectangle_set_border_width (rectangle,
|
||||
g_value_get_uint (value));
|
||||
break;
|
||||
case PROP_HAS_BORDER:
|
||||
rectangle->priv->has_border = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_rectangle_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterRectanglePrivate *priv = CLUTTER_RECTANGLE(object)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR:
|
||||
clutter_value_set_color (value, &priv->color);
|
||||
break;
|
||||
case PROP_BORDER_COLOR:
|
||||
clutter_value_set_color (value, &priv->border_color);
|
||||
break;
|
||||
case PROP_BORDER_WIDTH:
|
||||
g_value_set_uint (value, priv->border_width);
|
||||
break;
|
||||
case PROP_HAS_BORDER:
|
||||
g_value_set_boolean (value, priv->has_border);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clutter_rectangle_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (clutter_rectangle_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_rectangle_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (clutter_rectangle_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clutter_rectangle_class_init (ClutterRectangleClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
actor_class->paint = clutter_rectangle_paint;
|
||||
actor_class->get_paint_volume = clutter_rectangle_get_paint_volume;
|
||||
actor_class->has_overlaps = clutter_rectangle_has_overlaps;
|
||||
|
||||
gobject_class->finalize = clutter_rectangle_finalize;
|
||||
gobject_class->dispose = clutter_rectangle_dispose;
|
||||
gobject_class->set_property = clutter_rectangle_set_property;
|
||||
gobject_class->get_property = clutter_rectangle_get_property;
|
||||
|
||||
/**
|
||||
* ClutterRectangle:color:
|
||||
*
|
||||
* The color of the rectangle.
|
||||
*/
|
||||
pspec = clutter_param_spec_color ("color",
|
||||
P_("Color"),
|
||||
P_("The color of the rectangle"),
|
||||
&default_color,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_COLOR, pspec);
|
||||
|
||||
/**
|
||||
* ClutterRectangle:border-color:
|
||||
*
|
||||
* The color of the border of the rectangle.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
pspec = clutter_param_spec_color ("border-color",
|
||||
P_("Border Color"),
|
||||
P_("The color of the border of the rectangle"),
|
||||
&default_border_color,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_BORDER_COLOR, pspec);
|
||||
|
||||
/**
|
||||
* ClutterRectangle:border-width:
|
||||
*
|
||||
* The width of the border of the rectangle, in pixels.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_BORDER_WIDTH,
|
||||
g_param_spec_uint ("border-width",
|
||||
P_("Border Width"),
|
||||
P_("The width of the border of the rectangle"),
|
||||
0, G_MAXUINT,
|
||||
0,
|
||||
CLUTTER_PARAM_READWRITE));
|
||||
/**
|
||||
* ClutterRectangle:has-border:
|
||||
*
|
||||
* Whether the #ClutterRectangle should be displayed with a border.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_HAS_BORDER,
|
||||
g_param_spec_boolean ("has-border",
|
||||
P_("Has Border"),
|
||||
P_("Whether the rectangle should have a border"),
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_rectangle_init (ClutterRectangle *self)
|
||||
{
|
||||
ClutterRectanglePrivate *priv;
|
||||
|
||||
self->priv = priv = clutter_rectangle_get_instance_private (self);
|
||||
|
||||
priv->color = default_color;
|
||||
priv->border_color = default_border_color;
|
||||
|
||||
priv->border_width = 0;
|
||||
|
||||
priv->has_border = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_new:
|
||||
*
|
||||
* Creates a new #ClutterActor with a rectangular shape.
|
||||
*
|
||||
* Return value: a new #ClutterRectangle
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_new() instead
|
||||
*/
|
||||
ClutterActor*
|
||||
clutter_rectangle_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_RECTANGLE, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_new_with_color:
|
||||
* @color: a #ClutterColor
|
||||
*
|
||||
* Creates a new #ClutterActor with a rectangular shape
|
||||
* and of the given @color.
|
||||
*
|
||||
* Return value: a new #ClutterRectangle
|
||||
*
|
||||
* Deprecated: 1.10: Use clutter_actor_new() and
|
||||
* clutter_actor_set_background_color() instead
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_rectangle_new_with_color (const ClutterColor *color)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_RECTANGLE,
|
||||
"color", color,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_get_color:
|
||||
* @rectangle: a #ClutterRectangle
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
*
|
||||
* Retrieves the color of @rectangle.
|
||||
*
|
||||
* Deprecated: 1.10: Use #ClutterActor and clutter_actor_get_background_color()
|
||||
* instead
|
||||
*/
|
||||
void
|
||||
clutter_rectangle_get_color (ClutterRectangle *rectangle,
|
||||
ClutterColor *color)
|
||||
{
|
||||
ClutterRectanglePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
priv = rectangle->priv;
|
||||
|
||||
color->red = priv->color.red;
|
||||
color->green = priv->color.green;
|
||||
color->blue = priv->color.blue;
|
||||
color->alpha = priv->color.alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_set_color:
|
||||
* @rectangle: a #ClutterRectangle
|
||||
* @color: a #ClutterColor
|
||||
*
|
||||
* Sets the color of @rectangle.
|
||||
*
|
||||
* Deprecated: 1.10: Use #ClutterActor and clutter_actor_set_background_color()
|
||||
* instead
|
||||
*/
|
||||
void
|
||||
clutter_rectangle_set_color (ClutterRectangle *rectangle,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
ClutterRectanglePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
g_object_ref (rectangle);
|
||||
|
||||
priv = rectangle->priv;
|
||||
|
||||
priv->color.red = color->red;
|
||||
priv->color.green = color->green;
|
||||
priv->color.blue = color->blue;
|
||||
priv->color.alpha = color->alpha;
|
||||
|
||||
#if 0
|
||||
/* FIXME - appears to be causing border to always get drawn */
|
||||
if (clutter_color_equal (&priv->color, &priv->border_color))
|
||||
priv->has_border = FALSE;
|
||||
else
|
||||
priv->has_border = TRUE;
|
||||
#endif
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
|
||||
|
||||
g_object_notify (G_OBJECT (rectangle), "color");
|
||||
g_object_notify (G_OBJECT (rectangle), "has-border");
|
||||
g_object_unref (rectangle);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_get_border_width:
|
||||
* @rectangle: a #ClutterRectangle
|
||||
*
|
||||
* Gets the width (in pixels) of the border used by @rectangle
|
||||
*
|
||||
* Return value: the border's width
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content
|
||||
* to draw the border using Cairo
|
||||
*/
|
||||
guint
|
||||
clutter_rectangle_get_border_width (ClutterRectangle *rectangle)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_RECTANGLE (rectangle), 0);
|
||||
|
||||
return rectangle->priv->border_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_set_border_width:
|
||||
* @rectangle: a #ClutterRectangle
|
||||
* @width: the width of the border
|
||||
*
|
||||
* Sets the width (in pixel) of the border used by @rectangle.
|
||||
* A @width of 0 will unset the border.
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas content
|
||||
* to draw the border using Cairo
|
||||
*/
|
||||
void
|
||||
clutter_rectangle_set_border_width (ClutterRectangle *rectangle,
|
||||
guint width)
|
||||
{
|
||||
ClutterRectanglePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
|
||||
priv = rectangle->priv;
|
||||
|
||||
if (priv->border_width != width)
|
||||
{
|
||||
g_object_ref (rectangle);
|
||||
|
||||
priv->border_width = width;
|
||||
|
||||
if (priv->border_width != 0)
|
||||
priv->has_border = TRUE;
|
||||
else
|
||||
priv->has_border = FALSE;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
|
||||
|
||||
g_object_notify (G_OBJECT (rectangle), "border-width");
|
||||
g_object_notify (G_OBJECT (rectangle), "has-border");
|
||||
g_object_unref (rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_get_border_color:
|
||||
* @rectangle: a #ClutterRectangle
|
||||
* @color: (out caller-allocates): return location for a #ClutterColor
|
||||
*
|
||||
* Gets the color of the border used by @rectangle and places
|
||||
* it into @color.
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw
|
||||
* the border with Cairo
|
||||
*/
|
||||
void
|
||||
clutter_rectangle_get_border_color (ClutterRectangle *rectangle,
|
||||
ClutterColor *color)
|
||||
{
|
||||
ClutterRectanglePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
priv = rectangle->priv;
|
||||
|
||||
color->red = priv->border_color.red;
|
||||
color->green = priv->border_color.green;
|
||||
color->blue = priv->border_color.blue;
|
||||
color->alpha = priv->border_color.alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_rectangle_set_border_color:
|
||||
* @rectangle: a #ClutterRectangle
|
||||
* @color: the color of the border
|
||||
*
|
||||
* Sets the color of the border used by @rectangle using @color
|
||||
*
|
||||
* Deprecated: 1.10: Use #ClutterActor and a #ClutterCanvas to draw
|
||||
* the border with Cairo
|
||||
*/
|
||||
void
|
||||
clutter_rectangle_set_border_color (ClutterRectangle *rectangle,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
ClutterRectanglePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_RECTANGLE (rectangle));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
priv = rectangle->priv;
|
||||
|
||||
if (priv->border_color.red != color->red ||
|
||||
priv->border_color.green != color->green ||
|
||||
priv->border_color.blue != color->blue ||
|
||||
priv->border_color.alpha != color->alpha)
|
||||
{
|
||||
g_object_ref (rectangle);
|
||||
|
||||
priv->border_color.red = color->red;
|
||||
priv->border_color.green = color->green;
|
||||
priv->border_color.blue = color->blue;
|
||||
priv->border_color.alpha = color->alpha;
|
||||
|
||||
if (clutter_color_equal (&priv->color, &priv->border_color))
|
||||
priv->has_border = FALSE;
|
||||
else
|
||||
priv->has_border = TRUE;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (rectangle));
|
||||
|
||||
g_object_notify (G_OBJECT (rectangle), "border-color");
|
||||
g_object_notify (G_OBJECT (rectangle), "has-border");
|
||||
g_object_unref (rectangle);
|
||||
}
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_RECTANGLE_H__
|
||||
#define __CLUTTER_RECTANGLE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-color.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_RECTANGLE (clutter_rectangle_get_type())
|
||||
#define CLUTTER_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangle))
|
||||
#define CLUTTER_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass))
|
||||
#define CLUTTER_IS_RECTANGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_RECTANGLE))
|
||||
#define CLUTTER_IS_RECTANGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_RECTANGLE))
|
||||
#define CLUTTER_RECTANGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_RECTANGLE, ClutterRectangleClass))
|
||||
|
||||
typedef struct _ClutterRectangle ClutterRectangle;
|
||||
typedef struct _ClutterRectangleClass ClutterRectangleClass;
|
||||
typedef struct _ClutterRectanglePrivate ClutterRectanglePrivate;
|
||||
|
||||
/**
|
||||
* ClutterRectangle:
|
||||
*
|
||||
* The #ClutterRectangle structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
struct _ClutterRectangle
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActor parent;
|
||||
|
||||
ClutterRectanglePrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterRectangleClass:
|
||||
*
|
||||
* The #ClutterRectangleClass structure contains only private data
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
struct _ClutterRectangleClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_clutter_rectangle1) (void);
|
||||
void (*_clutter_rectangle2) (void);
|
||||
void (*_clutter_rectangle3) (void);
|
||||
void (*_clutter_rectangle4) (void);
|
||||
};
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
GType clutter_rectangle_get_type (void) G_GNUC_CONST;
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
|
||||
ClutterActor *clutter_rectangle_new (void);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_new)
|
||||
ClutterActor *clutter_rectangle_new_with_color (const ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color)
|
||||
void clutter_rectangle_get_color (ClutterRectangle *rectangle,
|
||||
ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
|
||||
void clutter_rectangle_set_color (ClutterRectangle *rectangle,
|
||||
const ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
guint clutter_rectangle_get_border_width (ClutterRectangle *rectangle);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_rectangle_set_border_width (ClutterRectangle *rectangle,
|
||||
guint width);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_rectangle_get_border_color (ClutterRectangle *rectangle,
|
||||
ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_rectangle_set_border_color (ClutterRectangle *rectangle,
|
||||
const ClutterColor *color);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_RECTANGLE_H__ */
|
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2011 Intel Corp
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_STAGE_DEPRECATED_H__
|
||||
#define __CLUTTER_STAGE_DEPRECATED_H__
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef CLUTTER_DISABLE_DEPRECATED
|
||||
|
||||
/**
|
||||
* CLUTTER_STAGE_WIDTH:
|
||||
*
|
||||
* Macro that evaluates to the width of the default stage
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.2: Use clutter_actor_get_width() instead
|
||||
*/
|
||||
#define CLUTTER_STAGE_WIDTH() (clutter_actor_get_width (clutter_stage_get_default ()))
|
||||
|
||||
/**
|
||||
* CLUTTER_STAGE_HEIGHT:
|
||||
*
|
||||
* Macro that evaluates to the height of the default stage
|
||||
*
|
||||
* Since: 0.2
|
||||
*
|
||||
* Deprecated: 1.2: use clutter_actor_get_height() instead
|
||||
*/
|
||||
#define CLUTTER_STAGE_HEIGHT() (clutter_actor_get_height (clutter_stage_get_default ()))
|
||||
|
||||
/* Commodity macro, for mallum only */
|
||||
#define clutter_stage_add(stage,actor) G_STMT_START { \
|
||||
if (CLUTTER_IS_STAGE ((stage)) && CLUTTER_IS_ACTOR ((actor))) \
|
||||
{ \
|
||||
ClutterContainer *_container = (ClutterContainer *) (stage); \
|
||||
ClutterActor *_actor = (ClutterActor *) (actor); \
|
||||
clutter_container_add_actor (_container, _actor); \
|
||||
} } G_STMT_END
|
||||
|
||||
#endif /* CLUTTER_DISABLE_DEPRECATED */
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_stage_new)
|
||||
ClutterActor * clutter_stage_get_default (void);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
gboolean clutter_stage_is_default (ClutterStage *stage);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_queue_redraw)
|
||||
void clutter_stage_queue_redraw (ClutterStage *stage);
|
||||
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_set_background_color)
|
||||
void clutter_stage_set_color (ClutterStage *stage,
|
||||
const ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_actor_get_background_color)
|
||||
void clutter_stage_get_color (ClutterStage *stage,
|
||||
ClutterColor *color);
|
||||
|
||||
CLUTTER_DEPRECATED
|
||||
void clutter_stage_ensure_current (ClutterStage *stage);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_DEPRECATED_H__ */
|
@@ -26,6 +26,9 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
CLUTTER_DEPRECATED_FOR(clutter_timeline_new_for_actor)
|
||||
ClutterTimeline * clutter_timeline_new (guint duration_ms);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_TIMELINE_PRIVATE_H__ */
|
||||
|
@@ -36,9 +36,9 @@ clutter_headers = [
|
||||
'clutter-feature.h',
|
||||
'clutter-fixed-layout.h',
|
||||
'clutter-flow-layout.h',
|
||||
'clutter-frame-clock.h',
|
||||
'clutter-gesture-action.h',
|
||||
'clutter-grid-layout.h',
|
||||
'clutter-group.h',
|
||||
'clutter-image.h',
|
||||
'clutter-input-device.h',
|
||||
'clutter-input-device-tool.h',
|
||||
@@ -123,6 +123,7 @@ clutter_sources = [
|
||||
'clutter-fixed-layout.c',
|
||||
'clutter-flatten-effect.c',
|
||||
'clutter-flow-layout.c',
|
||||
'clutter-frame-clock.c',
|
||||
'clutter-gesture-action.c',
|
||||
'clutter-graphene.c',
|
||||
'clutter-grid-layout.c',
|
||||
@@ -140,8 +141,6 @@ clutter_sources = [
|
||||
'clutter-layout-manager.c',
|
||||
'clutter-layout-meta.c',
|
||||
'clutter-main.c',
|
||||
'clutter-master-clock.c',
|
||||
'clutter-master-clock-default.c',
|
||||
'clutter-offscreen-effect.c',
|
||||
'clutter-page-turn-effect.c',
|
||||
'clutter-paint-context.c',
|
||||
@@ -199,8 +198,6 @@ clutter_private_headers = [
|
||||
'clutter-input-focus-private.h',
|
||||
'clutter-input-method-private.h',
|
||||
'clutter-input-pointer-a11y-private.h',
|
||||
'clutter-master-clock.h',
|
||||
'clutter-master-clock-default.h',
|
||||
'clutter-offscreen-effect-private.h',
|
||||
'clutter-paint-context-private.h',
|
||||
'clutter-paint-node-private.h',
|
||||
@@ -212,6 +209,7 @@ clutter_private_headers = [
|
||||
'clutter-stage-private.h',
|
||||
'clutter-stage-view-private.h',
|
||||
'clutter-stage-window.h',
|
||||
'clutter-timeline-private.h',
|
||||
]
|
||||
|
||||
clutter_nonintrospected_sources = [
|
||||
@@ -220,21 +218,10 @@ clutter_nonintrospected_sources = [
|
||||
]
|
||||
|
||||
clutter_deprecated_headers = [
|
||||
'deprecated/clutter-actor.h',
|
||||
'deprecated/clutter-box.h',
|
||||
'deprecated/clutter-container.h',
|
||||
'deprecated/clutter-group.h',
|
||||
'deprecated/clutter-rectangle.h',
|
||||
'deprecated/clutter-stage.h',
|
||||
'deprecated/clutter-timeline.h',
|
||||
]
|
||||
|
||||
clutter_deprecated_sources = [
|
||||
'deprecated/clutter-box.c',
|
||||
'deprecated/clutter-group.c',
|
||||
'deprecated/clutter-rectangle.c',
|
||||
]
|
||||
|
||||
clutter_backend_sources = []
|
||||
clutter_backend_nonintrospected_sources = [
|
||||
'cogl/clutter-stage-cogl.c',
|
||||
@@ -288,10 +275,8 @@ cally_headers = [
|
||||
'cally/cally-actor.h',
|
||||
'cally/cally-clone.h',
|
||||
'cally/cally-factory.h',
|
||||
'cally/cally-group.h',
|
||||
'cally/cally.h',
|
||||
'cally/cally-main.h',
|
||||
'cally/cally-rectangle.h',
|
||||
'cally/cally-root.h',
|
||||
'cally/cally-stage.h',
|
||||
'cally/cally-text.h',
|
||||
@@ -302,8 +287,6 @@ cally_sources = [
|
||||
'cally/cally-actor.c',
|
||||
'cally/cally.c',
|
||||
'cally/cally-clone.c',
|
||||
'cally/cally-group.c',
|
||||
'cally/cally-rectangle.c',
|
||||
'cally/cally-root.c',
|
||||
'cally/cally-stage.c',
|
||||
'cally/cally-text.c',
|
||||
@@ -385,7 +368,6 @@ libmutter_clutter = shared_library(libmutter_clutter_name,
|
||||
clutter_headers,
|
||||
clutter_private_headers,
|
||||
clutter_nonintrospected_sources,
|
||||
clutter_deprecated_sources,
|
||||
clutter_deprecated_headers,
|
||||
clutter_backend_sources,
|
||||
clutter_backend_nonintrospected_sources,
|
||||
@@ -431,7 +413,6 @@ if have_introspection
|
||||
clutter_built_headers,
|
||||
clutter_sources,
|
||||
clutter_headers,
|
||||
clutter_deprecated_sources,
|
||||
clutter_deprecated_headers,
|
||||
],
|
||||
nsversion: libmutter_api_version,
|
||||
|
@@ -8,6 +8,7 @@ clutter_c_args = [
|
||||
'-DCLUTTER_SYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)),
|
||||
'-DCLUTTER_COMPILATION=1',
|
||||
'-DCOGL_DISABLE_DEPRECATION_WARNINGS',
|
||||
'-DCOGL_ENABLE_MUTTER_API',
|
||||
'-DG_LOG_DOMAIN="Clutter"',
|
||||
]
|
||||
|
||||
|
@@ -45,6 +45,7 @@ struct _CoglFrameInfo
|
||||
int64_t global_frame_counter;
|
||||
};
|
||||
|
||||
CoglFrameInfo *_cogl_frame_info_new (void);
|
||||
COGL_EXPORT
|
||||
CoglFrameInfo *cogl_frame_info_new (int64_t global_frame_counter);
|
||||
|
||||
#endif /* __COGL_FRAME_INFO_PRIVATE_H */
|
||||
|
@@ -39,11 +39,12 @@ COGL_OBJECT_DEFINE (FrameInfo, frame_info);
|
||||
COGL_GTYPE_DEFINE_CLASS (FrameInfo, frame_info);
|
||||
|
||||
CoglFrameInfo *
|
||||
_cogl_frame_info_new (void)
|
||||
cogl_frame_info_new (int64_t global_frame_counter)
|
||||
{
|
||||
CoglFrameInfo *info;
|
||||
|
||||
info = g_slice_new0 (CoglFrameInfo);
|
||||
info->global_frame_counter = global_frame_counter;
|
||||
|
||||
return _cogl_frame_info_object_new (info);
|
||||
}
|
||||
|
@@ -45,6 +45,11 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* CoglFrameInfo:
|
||||
*
|
||||
* Frame information.
|
||||
*/
|
||||
typedef struct _CoglFrameInfo CoglFrameInfo;
|
||||
#define COGL_FRAME_INFO(X) ((CoglFrameInfo *)(X))
|
||||
|
||||
|
@@ -293,15 +293,14 @@ _cogl_onscreen_queue_event (CoglOnscreen *onscreen,
|
||||
void
|
||||
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
const CoglWinsysVtable *winsys;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
|
||||
info = _cogl_frame_info_new ();
|
||||
info->frame_counter = onscreen->frame_counter;
|
||||
g_queue_push_tail (&onscreen->pending_frame_infos, info);
|
||||
|
||||
@@ -310,7 +309,8 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
|
||||
winsys = _cogl_framebuffer_get_winsys (framebuffer);
|
||||
winsys->onscreen_swap_buffers_with_damage (onscreen,
|
||||
rectangles, n_rectangles);
|
||||
rectangles, n_rectangles,
|
||||
info);
|
||||
cogl_framebuffer_discard_buffers (framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
COGL_BUFFER_BIT_DEPTH |
|
||||
@@ -334,23 +334,23 @@ cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
}
|
||||
|
||||
void
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen)
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0);
|
||||
cogl_onscreen_swap_buffers_with_damage (onscreen, NULL, 0, info);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
const CoglWinsysVtable *winsys;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
|
||||
info = _cogl_frame_info_new ();
|
||||
info->frame_counter = onscreen->frame_counter;
|
||||
g_queue_push_tail (&onscreen->pending_frame_infos, info);
|
||||
|
||||
@@ -365,7 +365,8 @@ cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
|
||||
winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
n_rectangles,
|
||||
info);
|
||||
|
||||
cogl_framebuffer_discard_buffers (framebuffer,
|
||||
COGL_BUFFER_BIT_COLOR |
|
||||
@@ -406,22 +407,21 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen)
|
||||
}
|
||||
|
||||
void
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout)
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
const CoglWinsysVtable *winsys;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
g_return_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN);
|
||||
g_return_if_fail (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT));
|
||||
|
||||
info = _cogl_frame_info_new ();
|
||||
info->frame_counter = onscreen->frame_counter;
|
||||
g_queue_push_tail (&onscreen->pending_frame_infos, info);
|
||||
|
||||
winsys = _cogl_framebuffer_get_winsys (framebuffer);
|
||||
winsys->onscreen_direct_scanout (onscreen, scanout);
|
||||
winsys->onscreen_direct_scanout (onscreen, scanout, info);
|
||||
|
||||
onscreen->frame_counter++;
|
||||
}
|
||||
|
@@ -178,7 +178,8 @@ cogl_onscreen_hide (CoglOnscreen *onscreen);
|
||||
* Stability: unstable
|
||||
*/
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen);
|
||||
cogl_onscreen_swap_buffers (CoglOnscreen *onscreen,
|
||||
CoglFrameInfo *frame_info);
|
||||
|
||||
|
||||
/**
|
||||
@@ -284,14 +285,16 @@ cogl_onscreen_get_buffer_age (CoglOnscreen *onscreen);
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
/**
|
||||
* cogl_onscreen_direct_scanout: (skip)
|
||||
*/
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout);
|
||||
cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
/**
|
||||
* cogl_onscreen_swap_region:
|
||||
@@ -316,7 +319,8 @@ cogl_onscreen_direct_scanout (CoglOnscreen *onscreen,
|
||||
COGL_EXPORT void
|
||||
cogl_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
/**
|
||||
* CoglFrameEvent:
|
||||
|
@@ -402,6 +402,11 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
|
||||
{
|
||||
CoglContext *ctx = tex->context;
|
||||
|
||||
/* Since we are about to ask the GPU to generate mipmaps of tex, we
|
||||
* better make sure tex is up-to-date.
|
||||
*/
|
||||
_cogl_texture_flush_journal_rendering (tex);
|
||||
|
||||
ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d);
|
||||
|
||||
tex_2d->mipmaps_dirty = FALSE;
|
||||
|
@@ -77,6 +77,7 @@ cogl_headers = [
|
||||
'cogl-bitmap.h',
|
||||
'cogl-color.h',
|
||||
'cogl-context.h',
|
||||
'cogl-frame-info.h',
|
||||
'cogl-framebuffer.h',
|
||||
'cogl-matrix.h',
|
||||
'cogl-object.h',
|
||||
@@ -106,7 +107,6 @@ cogl_nonintrospected_headers = [
|
||||
'cogl-indices.h',
|
||||
'cogl-attribute.h',
|
||||
'cogl-primitive.h',
|
||||
'cogl-frame-info.h',
|
||||
'cogl-output.h',
|
||||
'cogl-matrix-stack.h',
|
||||
'cogl-poll.h',
|
||||
|
@@ -726,7 +726,8 @@ _cogl_winsys_onscreen_get_buffer_age (CoglOnscreen *onscreen)
|
||||
static void
|
||||
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
const int *user_rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
@@ -765,7 +766,8 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
static void
|
||||
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
|
@@ -1673,7 +1673,8 @@ set_frame_info_output (CoglOnscreen *onscreen,
|
||||
static void
|
||||
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
const int *user_rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *context = framebuffer->context;
|
||||
@@ -1879,7 +1880,8 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
|
||||
static void
|
||||
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *context = framebuffer->context;
|
||||
|
@@ -116,11 +116,13 @@ typedef struct _CoglWinsysVtable
|
||||
void
|
||||
(*onscreen_swap_buffers_with_damage) (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
void
|
||||
(*onscreen_direct_scanout) (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout);
|
||||
(*onscreen_direct_scanout) (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
void
|
||||
(*onscreen_set_visibility) (CoglOnscreen *onscreen,
|
||||
@@ -134,7 +136,8 @@ typedef struct _CoglWinsysVtable
|
||||
void
|
||||
(*onscreen_swap_region) (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles);
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *info);
|
||||
|
||||
void
|
||||
(*onscreen_set_resizable) (CoglOnscreen *onscreen, gboolean resizable);
|
||||
|
@@ -8,5 +8,5 @@ test_simple_rig (void)
|
||||
ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
|
||||
}
|
||||
|
@@ -185,9 +185,9 @@ test_multitexture (TestUtilsGTestFixture *fixture,
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
|
||||
|
||||
group = clutter_group_new ();
|
||||
group = clutter_actor_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
|
||||
|
||||
/* We force continuous redrawing incase someone comments out the
|
||||
@@ -197,7 +197,7 @@ test_multitexture (TestUtilsGTestFixture *fixture,
|
||||
|
||||
g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
|
@@ -156,7 +156,7 @@ test_readpixels (TestUtilsGTestFixture *fixture,
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
|
||||
|
||||
/* We force continuous redrawing of the stage, since we need to skip
|
||||
* the first few frames, and we wont be doing anything else that
|
||||
|
@@ -115,9 +115,9 @@ test_texture_mipmaps (TestUtilsGTestFixture *fixture,
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
|
||||
|
||||
group = clutter_group_new ();
|
||||
group = clutter_actor_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
|
||||
|
||||
/* We force continuous redrawing of the stage, since we need to skip
|
||||
@@ -127,7 +127,7 @@ test_texture_mipmaps (TestUtilsGTestFixture *fixture,
|
||||
|
||||
g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
|
@@ -217,14 +217,14 @@ test_texture_pixmap_x11 (TestUtilsGTestFixture *fixture,
|
||||
state.pixmap = create_pixmap (&state);
|
||||
state.tfp = cogl_texture_pixmap_x11_new (state.pixmap, TRUE);
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (state.stage), &stage_color);
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (state.stage), &stage_color);
|
||||
|
||||
paint_handler = g_signal_connect_after (state.stage, "paint",
|
||||
G_CALLBACK (on_paint), &state);
|
||||
|
||||
idle_handler = g_idle_add (queue_redraw, state.stage);
|
||||
|
||||
clutter_actor_show_all (state.stage);
|
||||
clutter_actor_show (state.stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
|
@@ -394,7 +394,7 @@ test_viewport (TestUtilsGTestFixture *fixture,
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color);
|
||||
|
||||
/* We force continuous redrawing of the stage, since we need to skip
|
||||
* the first few frames, and we wont be doing anything else that
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('mutter', 'c',
|
||||
version: '3.37.2',
|
||||
version: '3.37.3',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
4
po/ha.po
4
po/ha.po
@@ -1813,7 +1813,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
|
||||
msgstr ""
|
||||
"Wanda ya ɓata <halin firam=\"%s\" sake girma=\"%s\" zura ido=\"%s\" salo="
|
||||
"Wanda ya ɓata <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style="
|
||||
"\"komene ne\"/>"
|
||||
|
||||
#: ../src/ui/theme.c:4704
|
||||
@@ -1834,7 +1834,7 @@ msgid ""
|
||||
"type=\"%s\" style_set=\"whatever\"/> element"
|
||||
msgstr ""
|
||||
"Babu salon firam da aka daidaita wa nau'in taga \"%s\" cikin jigon \"%s\", "
|
||||
"ƙara wata ƙanshi na <nau'in taga=\"%s\" salon_daidaita=\"komene ne\"/>"
|
||||
"ƙara wata ƙanshi na <window type=\"%s\" style_set=\"komene ne\"/>"
|
||||
|
||||
#: ../src/ui/theme.c:5295 ../src/ui/theme.c:5357 ../src/ui/theme.c:5420
|
||||
#, c-format
|
||||
|
@@ -170,8 +170,6 @@ struct _MetaBackendPrivate
|
||||
guint sleep_signal_id;
|
||||
GCancellable *cancellable;
|
||||
GDBusConnection *system_bus;
|
||||
|
||||
gboolean was_headless;
|
||||
};
|
||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||
|
||||
@@ -292,19 +290,6 @@ meta_backend_monitors_changed (MetaBackend *backend)
|
||||
}
|
||||
|
||||
meta_cursor_renderer_force_update (priv->cursor_renderer);
|
||||
|
||||
if (meta_monitor_manager_is_headless (priv->monitor_manager) &&
|
||||
!priv->was_headless)
|
||||
{
|
||||
clutter_stage_freeze_updates (CLUTTER_STAGE (priv->stage));
|
||||
priv->was_headless = TRUE;
|
||||
}
|
||||
else if (!meta_monitor_manager_is_headless (priv->monitor_manager) &&
|
||||
priv->was_headless)
|
||||
{
|
||||
clutter_stage_thaw_updates (CLUTTER_STAGE (priv->stage));
|
||||
priv->was_headless = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "clutter/clutter.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "cogl/cogl.h"
|
||||
#include "core/boxes-private.h"
|
||||
#include "meta/meta-backend.h"
|
||||
#include "meta/util.h"
|
||||
|
||||
@@ -59,7 +60,7 @@ struct _MetaCursorRendererPrivate
|
||||
MetaCursorSprite *displayed_cursor;
|
||||
MetaOverlay *stage_overlay;
|
||||
gboolean handled_by_backend;
|
||||
guint post_paint_func_id;
|
||||
gulong after_paint_handler_id;
|
||||
|
||||
GList *hw_cursor_inhibitors;
|
||||
};
|
||||
@@ -153,17 +154,27 @@ queue_redraw (MetaCursorRenderer *renderer,
|
||||
texture, &rect);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_cursor_renderer_post_paint (gpointer data)
|
||||
static void
|
||||
meta_cursor_renderer_after_paint (ClutterStage *stage,
|
||||
ClutterStageView *stage_view,
|
||||
MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (data);
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
if (priv->displayed_cursor && !priv->handled_by_backend)
|
||||
meta_cursor_renderer_emit_painted (renderer, priv->displayed_cursor);
|
||||
{
|
||||
graphene_rect_t rect;
|
||||
MetaRectangle view_layout;
|
||||
graphene_rect_t view_rect;
|
||||
|
||||
return TRUE;
|
||||
rect = meta_cursor_renderer_calculate_rect (renderer,
|
||||
priv->displayed_cursor);
|
||||
clutter_stage_view_get_layout (stage_view, &view_layout);
|
||||
view_rect = meta_rectangle_to_graphene_rect (&view_layout);
|
||||
if (graphene_rect_intersection (&rect, &view_rect, NULL))
|
||||
meta_cursor_renderer_emit_painted (renderer, priv->displayed_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -228,11 +239,28 @@ meta_cursor_renderer_finalize (GObject *object)
|
||||
if (priv->stage_overlay)
|
||||
meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay);
|
||||
|
||||
clutter_threads_remove_repaint_func (priv->post_paint_func_id);
|
||||
g_clear_signal_handler (&priv->after_paint_handler_id, stage);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_constructed (GObject *object)
|
||||
{
|
||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object);
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = meta_backend_get_stage (priv->backend);
|
||||
priv->after_paint_handler_id =
|
||||
g_signal_connect (stage, "after-paint",
|
||||
G_CALLBACK (meta_cursor_renderer_after_paint),
|
||||
renderer);
|
||||
|
||||
G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
{
|
||||
@@ -241,6 +269,7 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
object_class->get_property = meta_cursor_renderer_get_property;
|
||||
object_class->set_property = meta_cursor_renderer_set_property;
|
||||
object_class->finalize = meta_cursor_renderer_finalize;
|
||||
object_class->constructed = meta_cursor_renderer_constructed;
|
||||
klass->update_cursor = meta_cursor_renderer_real_update_cursor;
|
||||
|
||||
obj_props[PROP_BACKEND] =
|
||||
@@ -265,14 +294,6 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
static void
|
||||
meta_cursor_renderer_init (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
priv->post_paint_func_id =
|
||||
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
|
||||
meta_cursor_renderer_post_paint,
|
||||
renderer,
|
||||
NULL);
|
||||
}
|
||||
|
||||
graphene_rect_t
|
||||
|
@@ -273,14 +273,6 @@ meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!session->screen_cast_session)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"No screen cast active");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -591,6 +583,15 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
|
||||
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||
return TRUE;
|
||||
|
||||
|
||||
if (!session->screen_cast_session)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"No screen cast active");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
||||
stream_path);
|
||||
if (!stream)
|
||||
@@ -628,6 +629,14 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
|
||||
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||
return TRUE;
|
||||
|
||||
if (!session->screen_cast_session)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"No screen cast active");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
||||
stream_path);
|
||||
if (!stream)
|
||||
@@ -666,6 +675,15 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
|
||||
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||
return TRUE;
|
||||
|
||||
|
||||
if (!session->screen_cast_session)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"No screen cast active");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
||||
stream_path);
|
||||
if (!stream)
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "backends/meta-renderer-view.h"
|
||||
|
||||
#include "backends/meta-crtc.h"
|
||||
#include "backends/meta-renderer.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "compositor/region-utils.h"
|
||||
@@ -41,6 +42,7 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_TRANSFORM,
|
||||
PROP_CRTC,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@@ -52,6 +54,8 @@ struct _MetaRendererView
|
||||
ClutterStageViewCogl parent;
|
||||
|
||||
MetaMonitorTransform transform;
|
||||
|
||||
MetaCrtc *crtc;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaRendererView, meta_renderer_view,
|
||||
@@ -63,6 +67,12 @@ meta_renderer_view_get_transform (MetaRendererView *view)
|
||||
return view->transform;
|
||||
}
|
||||
|
||||
MetaCrtc *
|
||||
meta_renderer_view_get_crtc (MetaRendererView *view)
|
||||
{
|
||||
return view->crtc;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_get_offscreen_transformation_matrix (ClutterStageView *view,
|
||||
CoglMatrix *matrix)
|
||||
@@ -161,6 +171,9 @@ meta_renderer_view_get_property (GObject *object,
|
||||
case PROP_TRANSFORM:
|
||||
g_value_set_uint (value, view->transform);
|
||||
break;
|
||||
case PROP_CRTC:
|
||||
g_value_set_object (value, view->crtc);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -180,6 +193,9 @@ meta_renderer_view_set_property (GObject *object,
|
||||
case PROP_TRANSFORM:
|
||||
meta_renderer_view_set_transform (view, g_value_get_uint (value));
|
||||
break;
|
||||
case PROP_CRTC:
|
||||
view->crtc = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -218,5 +234,14 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass)
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_CRTC] =
|
||||
g_param_spec_object ("crtc",
|
||||
"MetaCrtc",
|
||||
"MetaCrtc",
|
||||
META_TYPE_CRTC,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
@@ -28,4 +28,6 @@ G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view,
|
||||
|
||||
MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view);
|
||||
|
||||
MetaCrtc *meta_renderer_view_get_crtc (MetaRendererView *view);
|
||||
|
||||
#endif /* META_RENDERER_VIEW_H */
|
||||
|
@@ -64,6 +64,7 @@ typedef struct _MetaRendererPrivate
|
||||
{
|
||||
MetaBackend *backend;
|
||||
GList *views;
|
||||
gboolean is_paused;
|
||||
} MetaRendererPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaRenderer, meta_renderer, G_TYPE_OBJECT)
|
||||
@@ -127,11 +128,10 @@ create_crtc_view (MetaLogicalMonitor *logical_monitor,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaRenderer *renderer = user_data;
|
||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||
MetaRendererView *view;
|
||||
|
||||
view = meta_renderer_create_view (renderer, logical_monitor, output, crtc);
|
||||
priv->views = g_list_append (priv->views, view);
|
||||
meta_renderer_add_view (renderer, view);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -153,12 +153,94 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
|
||||
if (meta_logical_monitor_is_primary (logical_monitor))
|
||||
{
|
||||
ClutterBackend *clutter_backend;
|
||||
float scale;
|
||||
|
||||
clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
scale = meta_is_stage_views_scaled ()
|
||||
? meta_logical_monitor_get_scale (logical_monitor)
|
||||
: 1.f;
|
||||
|
||||
clutter_backend_set_fallback_resource_scale (clutter_backend, scale);
|
||||
}
|
||||
|
||||
meta_logical_monitor_foreach_crtc (logical_monitor,
|
||||
create_crtc_view,
|
||||
renderer);
|
||||
}
|
||||
}
|
||||
|
||||
static MetaRendererView *
|
||||
meta_renderer_get_view_for_crtc (MetaRenderer *renderer,
|
||||
MetaCrtc *crtc)
|
||||
{
|
||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->views; l; l = l->next)
|
||||
{
|
||||
MetaRendererView *view = l->data;
|
||||
|
||||
if (meta_renderer_view_get_crtc (view) == crtc)
|
||||
return view;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct _CollectViewsData
|
||||
{
|
||||
MetaRenderer *renderer;
|
||||
GList *out_views;
|
||||
} CollectViewsData;
|
||||
|
||||
static gboolean
|
||||
collect_views (MetaMonitor *monitor,
|
||||
MetaMonitorMode *mode,
|
||||
MetaMonitorCrtcMode *monitor_crtc_mode,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
CollectViewsData *data = user_data;
|
||||
MetaCrtc *crtc;
|
||||
MetaRendererView *view;
|
||||
|
||||
crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output);
|
||||
view = meta_renderer_get_view_for_crtc (data->renderer, crtc);
|
||||
if (!g_list_find (data->out_views, view))
|
||||
data->out_views = g_list_prepend (data->out_views, view);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GList *
|
||||
meta_renderer_real_get_views_for_monitor (MetaRenderer *renderer,
|
||||
MetaMonitor *monitor)
|
||||
{
|
||||
CollectViewsData data = { 0 };
|
||||
MetaMonitorMode *monitor_mode;
|
||||
|
||||
data.renderer = renderer;
|
||||
|
||||
monitor_mode = meta_monitor_get_current_mode (monitor);
|
||||
meta_monitor_mode_foreach_crtc (monitor, monitor_mode,
|
||||
collect_views,
|
||||
&data,
|
||||
NULL);
|
||||
|
||||
return data.out_views;
|
||||
}
|
||||
|
||||
GList *
|
||||
meta_renderer_get_views_for_monitor (MetaRenderer *renderer,
|
||||
MetaMonitor *monitor)
|
||||
{
|
||||
return META_RENDERER_GET_CLASS (renderer)->get_views_for_monitor (renderer,
|
||||
monitor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_renderer_add_view (MetaRenderer *renderer,
|
||||
MetaRendererView *view)
|
||||
@@ -166,6 +248,14 @@ meta_renderer_add_view (MetaRenderer *renderer,
|
||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||
|
||||
priv->views = g_list_append (priv->views, view);
|
||||
|
||||
if (priv->is_paused)
|
||||
{
|
||||
ClutterFrameClock *frame_clock =
|
||||
clutter_stage_view_get_frame_clock (CLUTTER_STAGE_VIEW (view));
|
||||
|
||||
clutter_frame_clock_inhibit (frame_clock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,6 +276,44 @@ meta_renderer_get_views (MetaRenderer *renderer)
|
||||
return priv->views;
|
||||
}
|
||||
|
||||
void
|
||||
meta_renderer_pause (MetaRenderer *renderer)
|
||||
{
|
||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (!priv->is_paused);
|
||||
priv->is_paused = TRUE;
|
||||
|
||||
for (l = priv->views; l; l = l->next)
|
||||
{
|
||||
ClutterStageView *stage_view = l->data;
|
||||
ClutterFrameClock *frame_clock =
|
||||
clutter_stage_view_get_frame_clock (stage_view);
|
||||
|
||||
clutter_frame_clock_inhibit (frame_clock);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_renderer_resume (MetaRenderer *renderer)
|
||||
{
|
||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (priv->is_paused);
|
||||
priv->is_paused = FALSE;
|
||||
|
||||
for (l = priv->views; l; l = l->next)
|
||||
{
|
||||
ClutterStageView *stage_view = l->data;
|
||||
ClutterFrameClock *frame_clock =
|
||||
clutter_stage_view_get_frame_clock (stage_view);
|
||||
|
||||
clutter_frame_clock_uninhibit (frame_clock);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_renderer_is_hardware_accelerated (MetaRenderer *renderer)
|
||||
{
|
||||
@@ -265,6 +393,7 @@ meta_renderer_class_init (MetaRendererClass *klass)
|
||||
object_class->finalize = meta_renderer_finalize;
|
||||
|
||||
klass->rebuild_views = meta_renderer_real_rebuild_views;
|
||||
klass->get_views_for_monitor = meta_renderer_real_get_views_for_monitor;
|
||||
|
||||
obj_props[PROP_BACKEND] =
|
||||
g_param_spec_object ("backend",
|
||||
|
@@ -46,6 +46,8 @@ struct _MetaRendererClass
|
||||
MetaOutput *output,
|
||||
MetaCrtc *crtc);
|
||||
void (* rebuild_views) (MetaRenderer *renderer);
|
||||
GList * (* get_views_for_monitor) (MetaRenderer *renderer,
|
||||
MetaMonitor *monitor);
|
||||
};
|
||||
|
||||
MetaBackend * meta_renderer_get_backend (MetaRenderer *renderer);
|
||||
@@ -57,9 +59,16 @@ void meta_renderer_rebuild_views (MetaRenderer *renderer);
|
||||
void meta_renderer_add_view (MetaRenderer *renderer,
|
||||
MetaRendererView *view);
|
||||
|
||||
GList * meta_renderer_get_views_for_monitor (MetaRenderer *renderer,
|
||||
MetaMonitor *monitor);
|
||||
|
||||
META_EXPORT_TEST
|
||||
GList * meta_renderer_get_views (MetaRenderer *renderer);
|
||||
|
||||
gboolean meta_renderer_is_hardware_accelerated (MetaRenderer *renderer);
|
||||
|
||||
void meta_renderer_pause (MetaRenderer *renderer);
|
||||
|
||||
void meta_renderer_resume (MetaRenderer *renderer);
|
||||
|
||||
#endif /* META_RENDERER_H */
|
||||
|
@@ -149,16 +149,32 @@ is_cursor_in_stream (MetaScreenCastAreaStreamSrc *area_src)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_redraw_queued (MetaScreenCastAreaStreamSrc *area_src)
|
||||
{
|
||||
ClutterStage *stage = get_stage (area_src);
|
||||
GList *l;
|
||||
|
||||
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
|
||||
{
|
||||
ClutterStageView *view = l->data;
|
||||
|
||||
if (clutter_stage_is_redraw_queued_on_view (stage, view))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
|
||||
ClutterStage *stage = get_stage (area_src);
|
||||
|
||||
if (!is_cursor_in_stream (area_src))
|
||||
return;
|
||||
|
||||
if (clutter_stage_is_redraw_queued (stage))
|
||||
if (is_redraw_queued (area_src))
|
||||
return;
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
|
@@ -176,16 +176,37 @@ is_cursor_in_stream (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_redraw_queued (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
MetaBackend *backend = get_backend (monitor_src);
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
ClutterStage *stage = get_stage (monitor_src);
|
||||
MetaMonitor *monitor = get_monitor (monitor_src);
|
||||
g_autoptr (GList) views = NULL;
|
||||
GList *l;
|
||||
|
||||
views = meta_renderer_get_views_for_monitor (renderer, monitor);
|
||||
for (l = views; l; l = l->next)
|
||||
{
|
||||
MetaRendererView *view = l->data;
|
||||
|
||||
if (clutter_stage_is_redraw_queued_on_view (stage, CLUTTER_STAGE_VIEW (view)))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||
ClutterStage *stage = get_stage (monitor_src);
|
||||
|
||||
if (!is_cursor_in_stream (monitor_src))
|
||||
return;
|
||||
|
||||
if (clutter_stage_is_redraw_queued (stage))
|
||||
if (is_redraw_queued (monitor_src))
|
||||
return;
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
@@ -371,12 +392,12 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
MetaMonitor *monitor;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
|
||||
stage = get_stage (monitor_src);
|
||||
if (!clutter_stage_is_redraw_queued (stage))
|
||||
if (!is_redraw_queued (monitor_src))
|
||||
return FALSE;
|
||||
|
||||
monitor = get_monitor (monitor_src);
|
||||
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||
stage = get_stage (monitor_src);
|
||||
clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
|
||||
|
||||
return TRUE;
|
||||
|
@@ -781,7 +781,6 @@ void
|
||||
meta_backend_native_pause (MetaBackendNative *native)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (native);
|
||||
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaMonitorManagerKms *monitor_manager_kms =
|
||||
@@ -789,12 +788,13 @@ meta_backend_native_pause (MetaBackendNative *native)
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
MetaSeatNative *seat =
|
||||
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (MetaBackendNativePause,
|
||||
"Backend (pause)");
|
||||
|
||||
meta_seat_native_release_devices (seat);
|
||||
clutter_stage_freeze_updates (stage);
|
||||
meta_renderer_pause (renderer);
|
||||
|
||||
disconnect_udev_device_added_handler (native);
|
||||
|
||||
@@ -814,6 +814,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
MetaSeatNative *seat =
|
||||
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
|
||||
COGL_TRACE_BEGIN_SCOPED (MetaBackendNativeResume,
|
||||
"Backend (resume)");
|
||||
@@ -823,7 +824,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
|
||||
connect_udev_device_added_handler (native);
|
||||
|
||||
meta_seat_native_reclaim_devices (seat);
|
||||
clutter_stage_thaw_updates (stage);
|
||||
meta_renderer_resume (renderer);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||
|
||||
|
@@ -169,8 +169,6 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
||||
MetaDumbBuffer dumb_fbs[2];
|
||||
} cpu;
|
||||
|
||||
int pending_flips;
|
||||
|
||||
gboolean noted_primary_gpu_copy_ok;
|
||||
gboolean noted_primary_gpu_copy_failed;
|
||||
MetaSharedFramebufferImportStatus import_status;
|
||||
@@ -199,15 +197,9 @@ typedef struct _MetaOnscreenNative
|
||||
} egl;
|
||||
#endif
|
||||
|
||||
gboolean pending_swap_notify;
|
||||
|
||||
gboolean pending_set_crtc;
|
||||
|
||||
int64_t pending_queue_swap_notify_frame_count;
|
||||
int64_t pending_swap_notify_frame_count;
|
||||
|
||||
MetaRendererView *view;
|
||||
int total_pending_flips;
|
||||
} MetaOnscreenNative;
|
||||
|
||||
struct _MetaRendererNative
|
||||
@@ -224,7 +216,6 @@ struct _MetaRendererNative
|
||||
|
||||
CoglClosure *swap_notify_idle;
|
||||
|
||||
int64_t frame_counter;
|
||||
gboolean pending_unset_disabled_crtcs;
|
||||
|
||||
GList *power_save_page_flip_onscreens;
|
||||
@@ -721,60 +712,6 @@ meta_renderer_native_disconnect (CoglRenderer *cogl_renderer)
|
||||
g_slice_free (CoglRendererEGL, cogl_renderer_egl);
|
||||
}
|
||||
|
||||
static void
|
||||
flush_pending_swap_notify (CoglFramebuffer *framebuffer)
|
||||
{
|
||||
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
|
||||
if (onscreen_native->pending_swap_notify)
|
||||
{
|
||||
CoglFrameInfo *info;
|
||||
|
||||
while ((info = g_queue_peek_head (&onscreen->pending_frame_infos)) &&
|
||||
info->global_frame_counter <= onscreen_native->pending_swap_notify_frame_count)
|
||||
{
|
||||
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
||||
_cogl_onscreen_notify_complete (onscreen, info);
|
||||
cogl_object_unref (info);
|
||||
g_queue_pop_head (&onscreen->pending_frame_infos);
|
||||
}
|
||||
|
||||
onscreen_native->pending_swap_notify = FALSE;
|
||||
cogl_object_unref (onscreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flush_pending_swap_notify_idle (void *user_data)
|
||||
{
|
||||
CoglContext *cogl_context = user_data;
|
||||
CoglRendererEGL *cogl_renderer_egl = cogl_context->display->renderer->winsys;
|
||||
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
||||
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
||||
GList *l;
|
||||
|
||||
/* This needs to be disconnected before invoking the callbacks in
|
||||
* case the callbacks cause it to be queued again */
|
||||
_cogl_closure_disconnect (renderer_native->swap_notify_idle);
|
||||
renderer_native->swap_notify_idle = NULL;
|
||||
|
||||
l = cogl_context->framebuffers;
|
||||
while (l)
|
||||
{
|
||||
GList *next = l->next;
|
||||
CoglFramebuffer *framebuffer = l->data;
|
||||
|
||||
flush_pending_swap_notify (framebuffer);
|
||||
|
||||
l = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
free_current_secondary_bo (CoglOnscreen *onscreen)
|
||||
{
|
||||
@@ -802,40 +739,14 @@ free_current_bo (CoglOnscreen *onscreen)
|
||||
static void
|
||||
meta_onscreen_native_queue_swap_notify (CoglOnscreen *onscreen)
|
||||
{
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
||||
CoglFrameInfo *info;
|
||||
|
||||
onscreen_native->pending_swap_notify_frame_count =
|
||||
onscreen_native->pending_queue_swap_notify_frame_count;
|
||||
g_assert (onscreen->pending_frame_infos.length == 1);
|
||||
|
||||
if (onscreen_native->pending_swap_notify)
|
||||
return;
|
||||
|
||||
/* We only want to notify that the swap is complete when the
|
||||
* application calls cogl_context_dispatch so instead of
|
||||
* immediately notifying we queue an idle callback */
|
||||
if (!renderer_native->swap_notify_idle)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *cogl_context = framebuffer->context;
|
||||
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
||||
|
||||
renderer_native->swap_notify_idle =
|
||||
_cogl_poll_renderer_add_idle (cogl_renderer,
|
||||
flush_pending_swap_notify_idle,
|
||||
cogl_context,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* The framebuffer will have its own referenc while the swap notify is
|
||||
* pending. Otherwise when destroying the view would drop the pending
|
||||
* notification with if the destruction happens before the idle callback
|
||||
* is invoked.
|
||||
*/
|
||||
cogl_object_ref (onscreen);
|
||||
onscreen_native->pending_swap_notify = TRUE;
|
||||
info = g_queue_pop_head (&onscreen->pending_frame_infos);
|
||||
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
||||
_cogl_onscreen_notify_complete (onscreen, info);
|
||||
cogl_object_unref (info);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1148,10 +1059,9 @@ notify_view_crtc_presented (MetaRendererView *view,
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
||||
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
||||
CoglFrameInfo *frame_info;
|
||||
MetaCrtc *crtc;
|
||||
MetaGpuKms *gpu_kms;
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
|
||||
/* Only keep the frame info for the fastest CRTC in use, which may not be
|
||||
* the first one to complete a flip. By only telling the compositor about the
|
||||
@@ -1163,35 +1073,21 @@ notify_view_crtc_presented (MetaRendererView *view,
|
||||
crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc));
|
||||
maybe_update_frame_info (crtc, frame_info, time_ns);
|
||||
|
||||
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
||||
if (gpu_kms != render_gpu)
|
||||
|
||||
meta_onscreen_native_queue_swap_notify (onscreen);
|
||||
|
||||
renderer_gpu_data =
|
||||
meta_renderer_native_get_gpu_data (renderer_native,
|
||||
onscreen_native->render_gpu);
|
||||
switch (renderer_gpu_data->mode)
|
||||
{
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state =
|
||||
onscreen_native->secondary_gpu_state;
|
||||
|
||||
secondary_gpu_state->pending_flips--;
|
||||
}
|
||||
|
||||
onscreen_native->total_pending_flips--;
|
||||
if (onscreen_native->total_pending_flips == 0)
|
||||
{
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
|
||||
meta_onscreen_native_queue_swap_notify (onscreen);
|
||||
|
||||
renderer_gpu_data =
|
||||
meta_renderer_native_get_gpu_data (renderer_native,
|
||||
onscreen_native->render_gpu);
|
||||
switch (renderer_gpu_data->mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
meta_onscreen_native_swap_drm_fb (onscreen);
|
||||
break;
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
meta_onscreen_native_swap_drm_fb (onscreen);
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
break;
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1405,10 +1301,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
||||
g_object_ref (view),
|
||||
kms_update);
|
||||
|
||||
onscreen_native->total_pending_flips++;
|
||||
if (secondary_gpu_state)
|
||||
secondary_gpu_state->pending_flips++;
|
||||
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
@@ -1418,7 +1310,6 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
||||
g_object_ref (view),
|
||||
custom_egl_stream_page_flip,
|
||||
onscreen_native);
|
||||
onscreen_native->total_pending_flips++;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
@@ -1486,40 +1377,6 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wait_for_pending_flips (CoglOnscreen *onscreen)
|
||||
{
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
||||
GError *error = NULL;
|
||||
|
||||
secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
||||
if (secondary_gpu_state)
|
||||
{
|
||||
while (secondary_gpu_state->pending_flips)
|
||||
{
|
||||
if (!meta_gpu_kms_wait_for_flip (secondary_gpu_state->gpu_kms, &error))
|
||||
{
|
||||
g_warning ("Failed to wait for flip on secondary GPU: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (onscreen_native->total_pending_flips)
|
||||
{
|
||||
if (!meta_gpu_kms_wait_for_flip (onscreen_native->render_gpu, &error))
|
||||
{
|
||||
g_warning ("Failed to wait for flip: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
import_shared_framebuffer (CoglOnscreen *onscreen,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
|
||||
@@ -2067,9 +1924,10 @@ ensure_crtc_modes (CoglOnscreen *onscreen,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles,
|
||||
CoglFrameInfo *frame_info)
|
||||
{
|
||||
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
@@ -2084,7 +1942,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
||||
CoglFrameInfo *frame_info;
|
||||
gboolean egl_context_changed = FALSE;
|
||||
MetaKmsUpdate *kms_update;
|
||||
g_autoptr (GError) error = NULL;
|
||||
@@ -2096,23 +1953,12 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
|
||||
kms_update = meta_kms_ensure_pending_update (kms);
|
||||
|
||||
/*
|
||||
* Wait for the flip callback before continuing, as we might have started the
|
||||
* animation earlier due to the animation being driven by some other monitor.
|
||||
*/
|
||||
COGL_TRACE_BEGIN (MetaRendererNativeSwapBuffersWait,
|
||||
"Onscreen (waiting for page flips)");
|
||||
wait_for_pending_flips (onscreen);
|
||||
COGL_TRACE_END (MetaRendererNativeSwapBuffersWait);
|
||||
|
||||
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
|
||||
frame_info->global_frame_counter = renderer_native->frame_counter;
|
||||
|
||||
update_secondary_gpu_state_pre_swap_buffers (onscreen);
|
||||
|
||||
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
n_rectangles,
|
||||
frame_info);
|
||||
|
||||
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
||||
render_gpu);
|
||||
@@ -2146,8 +1992,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
|
||||
|
||||
ensure_crtc_modes (onscreen, kms_update);
|
||||
|
||||
onscreen_native->pending_queue_swap_notify_frame_count = renderer_native->frame_counter;
|
||||
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
|
||||
|
||||
/*
|
||||
@@ -2296,8 +2140,9 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout)
|
||||
meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
||||
CoglScanout *scanout,
|
||||
CoglFrameInfo *frame_info)
|
||||
{
|
||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||
@@ -2311,17 +2156,11 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
||||
MetaBackend *backend = meta_renderer_get_backend (renderer);
|
||||
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
|
||||
MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
||||
CoglFrameInfo *frame_info;
|
||||
MetaKmsUpdate *kms_update;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
kms_update = meta_kms_ensure_pending_update (kms);
|
||||
|
||||
wait_for_pending_flips (onscreen);
|
||||
|
||||
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
|
||||
frame_info->global_frame_counter = renderer_native->frame_counter;
|
||||
|
||||
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
||||
render_gpu);
|
||||
|
||||
@@ -2331,9 +2170,6 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
||||
g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout));
|
||||
|
||||
ensure_crtc_modes (onscreen, kms_update);
|
||||
|
||||
onscreen_native->pending_queue_swap_notify_frame_count =
|
||||
renderer_native->frame_counter;
|
||||
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
|
||||
|
||||
meta_kms_post_pending_update_sync (kms);
|
||||
@@ -3247,12 +3083,15 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
&view_layout);
|
||||
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||
"name", meta_output_get_name (output),
|
||||
"stage", meta_backend_get_stage (backend),
|
||||
"layout", &view_layout,
|
||||
"crtc", crtc,
|
||||
"scale", scale,
|
||||
"framebuffer", onscreen,
|
||||
"offscreen", offscreen,
|
||||
"use-shadowfb", use_shadowfb,
|
||||
"transform", view_transform,
|
||||
"refresh-rate", crtc_mode_info->refresh_rate,
|
||||
NULL);
|
||||
g_clear_pointer (&offscreen, cogl_object_unref);
|
||||
|
||||
@@ -3305,8 +3144,6 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
|
||||
MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
||||
MetaKmsUpdate *kms_update = NULL;
|
||||
|
||||
renderer_native->frame_counter++;
|
||||
|
||||
if (renderer_native->pending_unset_disabled_crtcs)
|
||||
{
|
||||
GList *l;
|
||||
@@ -3346,12 +3183,6 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native)
|
||||
{
|
||||
return renderer_native->frame_counter;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_secondary_egl_config (MetaEgl *egl,
|
||||
MetaRendererNativeMode mode,
|
||||
|
@@ -55,8 +55,6 @@ MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_
|
||||
|
||||
void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
|
||||
|
||||
int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
|
||||
|
||||
gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
||||
uint32_t drm_format,
|
||||
uint64_t drm_modifier,
|
||||
|
@@ -885,13 +885,9 @@ meta_event_prepare (GSource *source,
|
||||
{
|
||||
gboolean retval;
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
|
||||
*timeout = -1;
|
||||
retval = clutter_events_pending ();
|
||||
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -901,13 +897,9 @@ meta_event_check (GSource *source)
|
||||
MetaEventSource *event_source = (MetaEventSource *) source;
|
||||
gboolean retval;
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
|
||||
retval = ((event_source->event_poll_fd.revents & G_IO_IN) ||
|
||||
clutter_events_pending ());
|
||||
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -1273,8 +1265,6 @@ meta_event_dispatch (GSource *g_source,
|
||||
MetaSeatNative *seat;
|
||||
ClutterEvent *event;
|
||||
|
||||
_clutter_threads_acquire_lock ();
|
||||
|
||||
seat = source->seat;
|
||||
|
||||
/* Don't queue more events if we haven't finished handling the previous batch
|
||||
@@ -1299,7 +1289,7 @@ meta_event_dispatch (GSource *g_source,
|
||||
|
||||
/* Drop events if we don't have any stage to forward them to */
|
||||
if (!_clutter_input_device_get_stage (input_device))
|
||||
goto out;
|
||||
return TRUE;
|
||||
|
||||
/* update the device states *before* the event */
|
||||
event_state = seat->button_state |
|
||||
@@ -1311,9 +1301,6 @@ meta_event_dispatch (GSource *g_source,
|
||||
_clutter_stage_queue_event (event->any.stage, event, FALSE);
|
||||
}
|
||||
|
||||
out:
|
||||
_clutter_threads_release_lock ();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
static GSourceFuncs event_funcs = {
|
||||
|
@@ -147,24 +147,6 @@ struct _MetaSeatNative
|
||||
G_DECLARE_FINAL_TYPE (MetaSeatNative, meta_seat_native,
|
||||
META, SEAT_NATIVE, ClutterSeat)
|
||||
|
||||
static inline uint64_t
|
||||
us (uint64_t us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
ms2us (uint64_t ms)
|
||||
{
|
||||
return us (ms * 1000);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
us2ms (uint64_t us)
|
||||
{
|
||||
return (uint32_t) (us / 1000);
|
||||
}
|
||||
|
||||
void meta_seat_native_notify_key (MetaSeatNative *seat,
|
||||
ClutterInputDevice *device,
|
||||
uint64_t time_us,
|
||||
|
@@ -52,86 +52,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaStageNative, meta_stage_native,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||
clutter_stage_window_iface_init))
|
||||
|
||||
static void
|
||||
frame_cb (CoglOnscreen *onscreen,
|
||||
CoglFrameEvent frame_event,
|
||||
CoglFrameInfo *frame_info,
|
||||
void *user_data)
|
||||
|
||||
{
|
||||
MetaStageNative *stage_native = user_data;
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_native);
|
||||
int64_t global_frame_counter;
|
||||
int64_t presented_frame_counter;
|
||||
ClutterFrameInfo clutter_frame_info;
|
||||
|
||||
global_frame_counter = cogl_frame_info_get_global_frame_counter (frame_info);
|
||||
|
||||
switch (frame_event)
|
||||
{
|
||||
case COGL_FRAME_EVENT_SYNC:
|
||||
presented_frame_counter = stage_native->presented_frame_counter_sync;
|
||||
stage_native->presented_frame_counter_sync = global_frame_counter;
|
||||
break;
|
||||
case COGL_FRAME_EVENT_COMPLETE:
|
||||
presented_frame_counter = stage_native->presented_frame_counter_complete;
|
||||
stage_native->presented_frame_counter_complete = global_frame_counter;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (global_frame_counter <= presented_frame_counter)
|
||||
return;
|
||||
|
||||
clutter_frame_info = (ClutterFrameInfo) {
|
||||
.frame_counter = global_frame_counter,
|
||||
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info),
|
||||
.presentation_time = cogl_frame_info_get_presentation_time (frame_info)
|
||||
};
|
||||
|
||||
_clutter_stage_cogl_presented (stage_cogl, frame_event, &clutter_frame_info);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_frame_callback (MetaStageNative *stage_native,
|
||||
ClutterStageView *stage_view)
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglOnscreen *onscreen;
|
||||
CoglClosure *closure;
|
||||
|
||||
closure = g_object_get_qdata (G_OBJECT (stage_view),
|
||||
quark_view_frame_closure);
|
||||
if (closure)
|
||||
return;
|
||||
|
||||
framebuffer = clutter_stage_view_get_onscreen (stage_view);
|
||||
onscreen = COGL_ONSCREEN (framebuffer);
|
||||
closure = cogl_onscreen_add_frame_callback (onscreen,
|
||||
frame_cb,
|
||||
stage_native,
|
||||
NULL);
|
||||
g_object_set_qdata (G_OBJECT (stage_view),
|
||||
quark_view_frame_closure,
|
||||
closure);
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_frame_callbacks (MetaStageNative *stage_native)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
GList *l;
|
||||
|
||||
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||
{
|
||||
ClutterStageView *stage_view = l->data;
|
||||
|
||||
ensure_frame_callback (stage_native, stage_view);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_native_rebuild_views (MetaStageNative *stage_native)
|
||||
{
|
||||
@@ -141,7 +61,6 @@ meta_stage_native_rebuild_views (MetaStageNative *stage_native)
|
||||
|
||||
meta_renderer_rebuild_views (renderer);
|
||||
clutter_stage_clear_stage_views (CLUTTER_STAGE (stage));
|
||||
ensure_frame_callbacks (stage_native);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -186,16 +105,6 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window)
|
||||
return meta_renderer_get_views (renderer);
|
||||
}
|
||||
|
||||
static int64_t
|
||||
meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
|
||||
return meta_renderer_native_get_frame_counter (renderer_native);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stage_native_finish_frame (ClutterStageWindow *stage_window)
|
||||
{
|
||||
@@ -225,6 +134,5 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
|
||||
iface->can_clip_redraws = meta_stage_native_can_clip_redraws;
|
||||
iface->get_geometry = meta_stage_native_get_geometry;
|
||||
iface->get_views = meta_stage_native_get_views;
|
||||
iface->get_frame_counter = meta_stage_native_get_frame_counter;
|
||||
iface->finish_frame = meta_stage_native_finish_frame;
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user