2010-05-25 10:10:37 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/* Theme node transitions for StWidget.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Florian Müllner <fmuellner@gnome.org>
|
|
|
|
*
|
|
|
|
* The St is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* The St 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
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with the St; see the file COPYING.LIB.
|
|
|
|
* If not, write to the Free Software Foundation, Inc., 59 Temple Place -
|
|
|
|
* Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "st-theme-node-transition.h"
|
|
|
|
|
|
|
|
enum {
|
|
|
|
COMPLETED,
|
|
|
|
NEW_FRAME,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
#define ST_THEME_NODE_TRANSITION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ST_TYPE_THEME_NODE_TRANSITION, StThemeNodeTransitionPrivate))
|
|
|
|
|
|
|
|
struct _StThemeNodeTransitionPrivate {
|
|
|
|
StThemeNode *old_theme_node;
|
|
|
|
StThemeNode *new_theme_node;
|
|
|
|
|
2010-07-22 12:53:58 -04:00
|
|
|
CoglHandle old_texture;
|
|
|
|
CoglHandle new_texture;
|
2010-05-25 10:10:37 -04:00
|
|
|
|
2010-07-22 12:53:58 -04:00
|
|
|
CoglHandle old_offscreen;
|
|
|
|
CoglHandle new_offscreen;
|
2010-05-25 10:10:37 -04:00
|
|
|
|
2010-07-22 12:53:58 -04:00
|
|
|
CoglHandle material;
|
2010-05-25 10:10:37 -04:00
|
|
|
|
|
|
|
ClutterAlpha *alpha;
|
|
|
|
ClutterTimeline *timeline;
|
|
|
|
|
|
|
|
guint timeline_completed_id;
|
|
|
|
guint timeline_new_frame_id;
|
|
|
|
|
|
|
|
ClutterActorBox last_allocation;
|
|
|
|
ClutterActorBox offscreen_box;
|
|
|
|
|
|
|
|
gboolean needs_setup;
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
2010-09-11 18:18:52 -04:00
|
|
|
/* template material to avoid unnecessary shader compilation */
|
|
|
|
static CoglHandle global_material = COGL_INVALID_HANDLE;
|
|
|
|
|
2010-05-25 10:10:37 -04:00
|
|
|
G_DEFINE_TYPE (StThemeNodeTransition, st_theme_node_transition, G_TYPE_OBJECT);
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_timeline_completed (ClutterTimeline *timeline,
|
|
|
|
StThemeNodeTransition *transition)
|
|
|
|
{
|
|
|
|
g_signal_emit (transition, signals[COMPLETED], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
on_timeline_new_frame (ClutterTimeline *timeline,
|
|
|
|
gint frame_num,
|
|
|
|
StThemeNodeTransition *transition)
|
|
|
|
{
|
|
|
|
g_signal_emit (transition, signals[NEW_FRAME], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
StThemeNodeTransition *
|
|
|
|
st_theme_node_transition_new (StThemeNode *from_node,
|
|
|
|
StThemeNode *to_node,
|
|
|
|
guint duration)
|
|
|
|
{
|
|
|
|
StThemeNodeTransition *transition;
|
|
|
|
|
|
|
|
g_return_val_if_fail (ST_IS_THEME_NODE (from_node), NULL);
|
|
|
|
g_return_val_if_fail (ST_IS_THEME_NODE (to_node), NULL);
|
|
|
|
|
|
|
|
duration = st_theme_node_get_transition_duration (to_node);
|
|
|
|
|
|
|
|
transition = g_object_new (ST_TYPE_THEME_NODE_TRANSITION,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
transition->priv->old_theme_node = g_object_ref (from_node);
|
|
|
|
transition->priv->new_theme_node = g_object_ref (to_node);
|
|
|
|
|
|
|
|
transition->priv->alpha = clutter_alpha_new ();
|
|
|
|
transition->priv->timeline = clutter_timeline_new (duration);
|
|
|
|
|
|
|
|
transition->priv->timeline_completed_id =
|
|
|
|
g_signal_connect (transition->priv->timeline, "completed",
|
|
|
|
G_CALLBACK (on_timeline_completed), transition);
|
|
|
|
transition->priv->timeline_new_frame_id =
|
|
|
|
g_signal_connect (transition->priv->timeline, "new-frame",
|
|
|
|
G_CALLBACK (on_timeline_new_frame), transition);
|
|
|
|
|
|
|
|
clutter_alpha_set_mode (transition->priv->alpha, CLUTTER_EASE_IN_OUT_QUAD);
|
|
|
|
clutter_alpha_set_timeline (transition->priv->alpha,
|
|
|
|
transition->priv->timeline);
|
|
|
|
|
|
|
|
clutter_timeline_start (transition->priv->timeline);
|
|
|
|
|
|
|
|
return transition;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
st_theme_node_transition_update (StThemeNodeTransition *transition,
|
|
|
|
StThemeNode *new_node)
|
|
|
|
{
|
|
|
|
StThemeNodeTransitionPrivate *priv = transition->priv;
|
|
|
|
StThemeNode *old_node;
|
|
|
|
ClutterTimelineDirection direction;
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_THEME_NODE_TRANSITION (transition));
|
|
|
|
g_return_if_fail (ST_IS_THEME_NODE (new_node));
|
|
|
|
|
|
|
|
direction = clutter_timeline_get_direction (priv->timeline);
|
|
|
|
old_node = (direction == CLUTTER_TIMELINE_FORWARD) ? priv->old_theme_node
|
|
|
|
: priv->new_theme_node;
|
|
|
|
|
|
|
|
/* If the update is the reversal of the current transition,
|
|
|
|
* we reverse the timeline.
|
|
|
|
* Otherwise, we should initiate a new transition from the
|
2010-06-09 04:56:19 -04:00
|
|
|
* current state to the new one; this is hard to do if the
|
|
|
|
* transition is in an intermediate state, so we just cancel
|
|
|
|
* the ongoing transition in that case.
|
2010-05-25 10:10:37 -04:00
|
|
|
* Note that reversing a timeline before any time elapsed
|
|
|
|
* results in the timeline's time position being set to the
|
|
|
|
* full duration - this is not what we want, so we cancel the
|
|
|
|
* transition as well in that case.
|
|
|
|
*/
|
2010-06-09 04:56:19 -04:00
|
|
|
if (st_theme_node_equal (new_node, old_node))
|
2010-05-25 10:10:37 -04:00
|
|
|
{
|
2010-06-09 04:56:19 -04:00
|
|
|
if (clutter_timeline_get_elapsed_time (priv->timeline) > 0)
|
|
|
|
{
|
|
|
|
if (direction == CLUTTER_TIMELINE_FORWARD)
|
|
|
|
clutter_timeline_set_direction (priv->timeline,
|
|
|
|
CLUTTER_TIMELINE_BACKWARD);
|
|
|
|
else
|
|
|
|
clutter_timeline_set_direction (priv->timeline,
|
|
|
|
CLUTTER_TIMELINE_FORWARD);
|
|
|
|
}
|
2010-05-25 10:10:37 -04:00
|
|
|
else
|
2010-06-09 04:56:19 -04:00
|
|
|
{
|
|
|
|
clutter_timeline_stop (priv->timeline);
|
|
|
|
g_signal_emit (transition, signals[COMPLETED], 0);
|
|
|
|
}
|
2010-05-25 10:10:37 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-09 04:56:19 -04:00
|
|
|
if (clutter_timeline_get_elapsed_time (priv->timeline) > 0)
|
|
|
|
{
|
|
|
|
clutter_timeline_stop (priv->timeline);
|
|
|
|
g_signal_emit (transition, signals[COMPLETED], 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
guint new_duration = st_theme_node_get_transition_duration (new_node);
|
|
|
|
|
|
|
|
clutter_timeline_set_duration (priv->timeline, new_duration);
|
2010-08-26 14:10:46 -04:00
|
|
|
|
|
|
|
/* If the change doesn't affect painting, we don't need to redraw,
|
|
|
|
* but we still need to replace the node so that we properly share
|
|
|
|
* caching with the painting that happens after the transition finishes.
|
|
|
|
*/
|
|
|
|
if (!st_theme_node_paint_equal (priv->new_theme_node, new_node))
|
|
|
|
priv->needs_setup = TRUE;
|
|
|
|
|
2010-06-09 04:56:19 -04:00
|
|
|
g_object_unref (priv->new_theme_node);
|
|
|
|
priv->new_theme_node = g_object_ref (new_node);
|
|
|
|
}
|
2010-05-25 10:10:37 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
calculate_offscreen_box (StThemeNodeTransition *transition,
|
|
|
|
const ClutterActorBox *allocation)
|
|
|
|
{
|
|
|
|
StThemeNodeTransitionPrivate *priv = transition->priv;
|
|
|
|
ClutterActorBox old_node_box, new_node_box;
|
|
|
|
|
|
|
|
st_theme_node_get_paint_box (priv->old_theme_node,
|
|
|
|
allocation,
|
|
|
|
&old_node_box);
|
|
|
|
|
|
|
|
st_theme_node_get_paint_box (priv->new_theme_node,
|
|
|
|
allocation,
|
|
|
|
&new_node_box);
|
|
|
|
|
|
|
|
priv->offscreen_box.x1 = MIN (old_node_box.x1, new_node_box.x1)
|
|
|
|
- allocation->x1;
|
|
|
|
priv->offscreen_box.y1 = MIN (old_node_box.y1, new_node_box.y1)
|
|
|
|
- allocation->y1;
|
|
|
|
priv->offscreen_box.x2 = MAX (old_node_box.x2, new_node_box.x2)
|
|
|
|
- allocation->x1;
|
|
|
|
priv->offscreen_box.y2 = MAX (old_node_box.y2, new_node_box.y2)
|
|
|
|
- allocation->y1;
|
|
|
|
}
|
|
|
|
|
2010-06-12 12:54:08 -04:00
|
|
|
static gboolean
|
2010-05-25 10:10:37 -04:00
|
|
|
setup_framebuffers (StThemeNodeTransition *transition,
|
2010-08-17 07:30:12 -04:00
|
|
|
const ClutterActorBox *allocation)
|
2010-05-25 10:10:37 -04:00
|
|
|
{
|
|
|
|
StThemeNodeTransitionPrivate *priv = transition->priv;
|
|
|
|
CoglColor clear_color = { 0, 0, 0, 0 };
|
|
|
|
guint width, height;
|
|
|
|
|
|
|
|
width = priv->offscreen_box.x2 - priv->offscreen_box.x1;
|
|
|
|
height = priv->offscreen_box.y2 - priv->offscreen_box.y1;
|
|
|
|
|
2010-06-12 12:54:08 -04:00
|
|
|
g_return_val_if_fail (width > 0, FALSE);
|
|
|
|
g_return_val_if_fail (height > 0, FALSE);
|
|
|
|
|
2010-05-25 10:10:37 -04:00
|
|
|
if (priv->old_texture)
|
|
|
|
cogl_handle_unref (priv->old_texture);
|
|
|
|
priv->old_texture = cogl_texture_new_with_size (width, height,
|
|
|
|
COGL_TEXTURE_NO_SLICING,
|
|
|
|
COGL_PIXEL_FORMAT_ANY);
|
|
|
|
|
|
|
|
if (priv->new_texture)
|
|
|
|
cogl_handle_unref (priv->new_texture);
|
|
|
|
priv->new_texture = cogl_texture_new_with_size (width, height,
|
|
|
|
COGL_TEXTURE_NO_SLICING,
|
|
|
|
COGL_PIXEL_FORMAT_ANY);
|
|
|
|
|
2010-06-12 12:54:08 -04:00
|
|
|
g_return_val_if_fail (priv->old_texture != COGL_INVALID_HANDLE, FALSE);
|
|
|
|
g_return_val_if_fail (priv->new_texture != COGL_INVALID_HANDLE, FALSE);
|
|
|
|
|
2010-05-25 10:10:37 -04:00
|
|
|
if (priv->old_offscreen)
|
|
|
|
cogl_handle_unref (priv->old_offscreen);
|
|
|
|
priv->old_offscreen = cogl_offscreen_new_to_texture (priv->old_texture);
|
|
|
|
|
|
|
|
if (priv->new_offscreen)
|
|
|
|
cogl_handle_unref (priv->new_offscreen);
|
|
|
|
priv->new_offscreen = cogl_offscreen_new_to_texture (priv->new_texture);
|
|
|
|
|
2010-06-12 12:54:08 -04:00
|
|
|
g_return_val_if_fail (priv->old_offscreen != COGL_INVALID_HANDLE, FALSE);
|
|
|
|
g_return_val_if_fail (priv->new_offscreen != COGL_INVALID_HANDLE, FALSE);
|
|
|
|
|
2010-09-11 18:18:52 -04:00
|
|
|
if (priv->material == NULL)
|
|
|
|
{
|
|
|
|
if (G_UNLIKELY (global_material == COGL_INVALID_HANDLE))
|
|
|
|
{
|
|
|
|
global_material = cogl_material_new ();
|
|
|
|
|
|
|
|
cogl_material_set_layer_combine (global_material, 0,
|
|
|
|
"RGBA = REPLACE (TEXTURE)",
|
|
|
|
NULL);
|
|
|
|
cogl_material_set_layer_combine (global_material, 1,
|
|
|
|
"RGBA = INTERPOLATE (PREVIOUS, "
|
|
|
|
"TEXTURE, "
|
|
|
|
"CONSTANT[A])",
|
|
|
|
NULL);
|
|
|
|
cogl_material_set_layer_combine (global_material, 2,
|
|
|
|
"RGBA = MODULATE (PREVIOUS, "
|
|
|
|
"PRIMARY)",
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
priv->material = cogl_material_copy (global_material);
|
|
|
|
}
|
2010-05-25 10:10:37 -04:00
|
|
|
|
|
|
|
cogl_material_set_layer (priv->material, 0, priv->new_texture);
|
|
|
|
cogl_material_set_layer (priv->material, 1, priv->old_texture);
|
|
|
|
|
|
|
|
cogl_push_framebuffer (priv->old_offscreen);
|
|
|
|
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
|
|
|
|
cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
|
|
|
|
priv->offscreen_box.y2, priv->offscreen_box.y1,
|
|
|
|
0.0, 1.0);
|
2010-08-17 07:30:12 -04:00
|
|
|
st_theme_node_paint (priv->old_theme_node, allocation, 255);
|
2010-05-25 10:10:37 -04:00
|
|
|
cogl_pop_framebuffer ();
|
|
|
|
|
|
|
|
cogl_push_framebuffer (priv->new_offscreen);
|
|
|
|
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
|
|
|
|
cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
|
|
|
|
priv->offscreen_box.y2, priv->offscreen_box.y1,
|
|
|
|
0.0, 1.0);
|
2010-08-17 07:30:12 -04:00
|
|
|
st_theme_node_paint (priv->new_theme_node, allocation, 255);
|
2010-05-25 10:10:37 -04:00
|
|
|
cogl_pop_framebuffer ();
|
2010-06-12 12:54:08 -04:00
|
|
|
|
|
|
|
return TRUE;
|
2010-05-25 10:10:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
st_theme_node_transition_paint (StThemeNodeTransition *transition,
|
|
|
|
ClutterActorBox *allocation,
|
|
|
|
guint8 paint_opacity)
|
|
|
|
{
|
|
|
|
StThemeNodeTransitionPrivate *priv = transition->priv;
|
|
|
|
|
2010-06-08 14:38:32 -04:00
|
|
|
CoglColor constant;
|
2010-05-25 10:10:37 -04:00
|
|
|
float tex_coords[] = {
|
|
|
|
0.0, 0.0, 1.0, 1.0,
|
|
|
|
0.0, 0.0, 1.0, 1.0,
|
|
|
|
};
|
|
|
|
|
|
|
|
g_return_if_fail (ST_IS_THEME_NODE (priv->old_theme_node));
|
|
|
|
g_return_if_fail (ST_IS_THEME_NODE (priv->new_theme_node));
|
|
|
|
|
2010-08-17 07:30:12 -04:00
|
|
|
if (!clutter_actor_box_equal (allocation, &priv->last_allocation))
|
2010-05-25 10:10:37 -04:00
|
|
|
priv->needs_setup = TRUE;
|
|
|
|
|
|
|
|
if (priv->needs_setup)
|
|
|
|
{
|
|
|
|
priv->last_allocation = *allocation;
|
|
|
|
|
|
|
|
calculate_offscreen_box (transition, allocation);
|
2010-08-17 07:30:12 -04:00
|
|
|
priv->needs_setup = !setup_framebuffers (transition, allocation);
|
2010-05-25 10:10:37 -04:00
|
|
|
}
|
|
|
|
|
2010-08-17 07:30:12 -04:00
|
|
|
cogl_color_set_from_4f (&constant, 0., 0., 0.,
|
|
|
|
clutter_alpha_get_alpha (priv->alpha));
|
2010-05-25 10:10:37 -04:00
|
|
|
cogl_material_set_layer_combine_constant (priv->material, 1, &constant);
|
|
|
|
|
2010-08-17 07:30:12 -04:00
|
|
|
cogl_material_set_color4ub (priv->material,
|
|
|
|
paint_opacity, paint_opacity,
|
|
|
|
paint_opacity, paint_opacity);
|
|
|
|
|
2010-05-25 10:10:37 -04:00
|
|
|
cogl_set_source (priv->material);
|
|
|
|
cogl_rectangle_with_multitexture_coords (priv->offscreen_box.x1,
|
|
|
|
priv->offscreen_box.y1,
|
|
|
|
priv->offscreen_box.x2,
|
|
|
|
priv->offscreen_box.y2,
|
|
|
|
tex_coords, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_theme_node_transition_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
StThemeNodeTransitionPrivate *priv = ST_THEME_NODE_TRANSITION (object)->priv;
|
|
|
|
|
|
|
|
if (priv->old_theme_node)
|
|
|
|
{
|
|
|
|
g_object_unref (priv->old_theme_node);
|
|
|
|
priv->old_theme_node = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->new_theme_node)
|
|
|
|
{
|
|
|
|
g_object_unref (priv->new_theme_node);
|
|
|
|
priv->new_theme_node = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->old_texture)
|
|
|
|
{
|
|
|
|
cogl_handle_unref (priv->old_texture);
|
|
|
|
priv->old_texture = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->new_texture)
|
|
|
|
{
|
|
|
|
cogl_handle_unref (priv->new_texture);
|
|
|
|
priv->new_texture = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->old_offscreen)
|
|
|
|
{
|
|
|
|
cogl_handle_unref (priv->old_offscreen);
|
|
|
|
priv->old_offscreen = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->new_offscreen)
|
|
|
|
{
|
|
|
|
cogl_handle_unref (priv->new_offscreen);
|
|
|
|
priv->new_offscreen = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->material)
|
|
|
|
{
|
|
|
|
cogl_handle_unref (priv->material);
|
|
|
|
priv->material = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->timeline)
|
|
|
|
{
|
|
|
|
if (priv->timeline_completed_id != 0)
|
|
|
|
g_signal_handler_disconnect (priv->timeline,
|
|
|
|
priv->timeline_completed_id);
|
|
|
|
if (priv->timeline_new_frame_id != 0)
|
|
|
|
g_signal_handler_disconnect (priv->timeline,
|
|
|
|
priv->timeline_new_frame_id);
|
|
|
|
|
|
|
|
g_object_unref (priv->timeline);
|
|
|
|
priv->timeline = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->timeline_completed_id = 0;
|
|
|
|
priv->timeline_new_frame_id = 0;
|
|
|
|
|
|
|
|
if (priv->alpha)
|
|
|
|
{
|
|
|
|
g_object_unref (priv->alpha);
|
|
|
|
priv->alpha = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (st_theme_node_transition_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_theme_node_transition_init (StThemeNodeTransition *transition)
|
|
|
|
{
|
|
|
|
transition->priv = ST_THEME_NODE_TRANSITION_GET_PRIVATE (transition);
|
|
|
|
|
|
|
|
transition->priv->old_theme_node = NULL;
|
|
|
|
transition->priv->new_theme_node = NULL;
|
|
|
|
|
|
|
|
transition->priv->old_texture = NULL;
|
|
|
|
transition->priv->new_texture = NULL;
|
|
|
|
|
|
|
|
transition->priv->old_offscreen = NULL;
|
|
|
|
transition->priv->new_offscreen = NULL;
|
|
|
|
|
|
|
|
transition->priv->needs_setup = TRUE;
|
|
|
|
|
|
|
|
transition->priv->alpha = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
st_theme_node_transition_class_init (StThemeNodeTransitionClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
g_type_class_add_private (klass, sizeof (StThemeNodeTransitionPrivate));
|
|
|
|
|
|
|
|
object_class->dispose = st_theme_node_transition_dispose;
|
|
|
|
|
|
|
|
signals[COMPLETED] =
|
|
|
|
g_signal_new ("completed",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
G_STRUCT_OFFSET (StThemeNodeTransitionClass, completed),
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
|
|
|
|
signals[NEW_FRAME] =
|
|
|
|
g_signal_new ("new-frame",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
G_STRUCT_OFFSET (StThemeNodeTransitionClass, new_frame),
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
}
|