2 * Copyright (C) 2006-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
24 #include "swfdec_actor.h"
25 #include "swfdec_as_internal.h"
26 #include "swfdec_as_strings.h"
27 #include "swfdec_debug.h"
28 #include "swfdec_button_movie.h"
29 #include "swfdec_player_internal.h"
30 #include "swfdec_resource.h"
31 #include "swfdec_sandbox.h"
32 #include "swfdec_sprite_movie.h"
35 G_DEFINE_ABSTRACT_TYPE (SwfdecActor
, swfdec_actor
, SWFDEC_TYPE_MOVIE
)
38 swfdec_actor_dispose (GObject
*object
)
40 SwfdecActor
*actor
= SWFDEC_ACTOR (object
);
43 swfdec_event_list_free (actor
->events
);
47 G_OBJECT_CLASS (swfdec_actor_parent_class
)->dispose (object
);
51 swfdec_actor_iterate_end (SwfdecActor
*actor
)
53 SwfdecMovie
*movie
= SWFDEC_MOVIE (actor
);
55 return movie
->parent
== NULL
||
56 movie
->state
< SWFDEC_MOVIE_STATE_REMOVED
;
60 swfdec_actor_mouse_events (SwfdecActor
*actor
)
62 SwfdecAsObject
*object
;
64 /* root movies don't get event */
65 if (SWFDEC_MOVIE (actor
)->parent
== NULL
)
67 /* look if we have a script that gets events */
68 if (actor
->events
&& swfdec_event_list_has_mouse_events (actor
->events
))
70 /* otherwise, require at least one of the custom script handlers */
71 object
= swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (actor
));
72 if (swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onRollOver
) ||
73 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onRollOut
) ||
74 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onDragOver
) ||
75 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onDragOut
) ||
76 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onPress
) ||
77 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onRelease
) ||
78 swfdec_as_object_has_variable (object
, SWFDEC_AS_STR_onReleaseOutside
))
84 swfdec_actor_mouse_in (SwfdecActor
*actor
)
86 if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
))))
87 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_DRAG_OVER
);
89 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_ROLL_OVER
);
93 swfdec_actor_mouse_out (SwfdecActor
*actor
)
95 if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
))))
96 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_DRAG_OUT
);
98 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_ROLL_OUT
);
102 swfdec_actor_mouse_press (SwfdecActor
*actor
, guint button
)
106 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_PRESS
);
110 swfdec_actor_mouse_release (SwfdecActor
*actor
, guint button
)
112 SwfdecPlayer
*player
;
117 player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
));
118 if (player
->priv
->mouse_below
== actor
)
119 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_RELEASE
);
121 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_RELEASE_OUTSIDE
);
125 swfdec_actor_mouse_move (SwfdecActor
*actor
, double x
, double y
)
127 /* nothing to do here, it's just there so we don't need to check for NULL */
131 swfdec_actor_key_press (SwfdecActor
*actor
, guint keycode
, guint character
)
133 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_KEY_DOWN
);
137 swfdec_actor_key_release (SwfdecActor
*actor
, guint keycode
, guint character
)
139 swfdec_actor_queue_script (actor
, SWFDEC_EVENT_KEY_UP
);
143 swfdec_actor_constructor (GType type
, guint n_construct_properties
,
144 GObjectConstructParam
*construct_properties
)
146 SwfdecPlayerPrivate
*priv
;
149 object
= G_OBJECT_CLASS (swfdec_actor_parent_class
)->constructor (type
,
150 n_construct_properties
, construct_properties
);
152 priv
= SWFDEC_PLAYER (swfdec_gc_object_get_context (object
))->priv
;
153 /* NB: adding to the movies list happens before swfdec_movie_initialize().
154 * swfdec_movie_initialize() does a gotoAndPlay(0) for Sprites which can
155 * cause new movies to be created (and added to this list).
157 priv
->actors
= g_list_prepend (priv
->actors
, object
);
163 swfdec_actor_class_init (SwfdecActorClass
*klass
)
165 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
167 object_class
->constructor
= swfdec_actor_constructor
;
168 object_class
->dispose
= swfdec_actor_dispose
;
170 klass
->iterate_end
= swfdec_actor_iterate_end
;
171 klass
->mouse_events
= swfdec_actor_mouse_events
;
172 klass
->mouse_in
= swfdec_actor_mouse_in
;
173 klass
->mouse_out
= swfdec_actor_mouse_out
;
174 klass
->mouse_press
= swfdec_actor_mouse_press
;
175 klass
->mouse_release
= swfdec_actor_mouse_release
;
176 klass
->mouse_move
= swfdec_actor_mouse_move
;
177 klass
->key_press
= swfdec_actor_key_press
;
178 klass
->key_release
= swfdec_actor_key_release
;
182 swfdec_actor_init (SwfdecActor
*actor
)
184 swfdec_sound_matrix_init_identity (&actor
->sound_matrix
);
188 swfdec_sprite_movie_set_constructor (SwfdecSpriteMovie
*movie
)
190 SwfdecMovie
*mov
= SWFDEC_MOVIE (movie
);
191 SwfdecAsContext
*context
= swfdec_gc_object_get_context (movie
);
192 SwfdecAsObject
*constructor
= NULL
;
193 SwfdecAsObject
*object
= swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (movie
));
195 g_assert (mov
->resource
!= NULL
);
200 name
= swfdec_resource_get_export_name (mov
->resource
,
201 SWFDEC_CHARACTER (movie
->sprite
));
203 name
= swfdec_as_context_get_string (context
, name
);
204 constructor
= swfdec_player_get_export_class (SWFDEC_PLAYER (context
),
208 if (constructor
== NULL
) {
209 swfdec_sandbox_use (SWFDEC_MOVIE (movie
)->resource
->sandbox
);
210 swfdec_as_object_set_constructor_by_name (object
,
211 SWFDEC_AS_STR_MovieClip
, NULL
);
212 swfdec_sandbox_unuse (SWFDEC_MOVIE (movie
)->resource
->sandbox
);
215 swfdec_as_object_set_constructor (object
, constructor
);
221 swfdec_actor_execute (SwfdecActor
*actor
, SwfdecEventType condition
,
227 gboolean need_constructor
= FALSE
;
229 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
231 version
= swfdec_movie_get_version (SWFDEC_MOVIE (actor
));
233 if (SWFDEC_IS_BUTTON_MOVIE (actor
)) {
234 /* these conditions don't exist for buttons */
235 if (condition
== SWFDEC_EVENT_CONSTRUCT
|| condition
< SWFDEC_EVENT_PRESS
)
237 thisp
= SWFDEC_MOVIE (actor
)->parent
;
239 while (!SWFDEC_IS_SPRITE_MOVIE (thisp
))
240 thisp
= SWFDEC_MOVIE (thisp
)->parent
;
244 thisp
= SWFDEC_MOVIE (actor
);
248 if (condition
== SWFDEC_EVENT_CONSTRUCT
) {
251 need_constructor
= swfdec_sprite_movie_set_constructor (SWFDEC_SPRITE_MOVIE (actor
));
252 } else if (condition
== SWFDEC_EVENT_ENTER
) {
253 if (SWFDEC_MOVIE (actor
)->state
>= SWFDEC_MOVIE_STATE_REMOVED
)
255 } else if (condition
== SWFDEC_EVENT_SCROLL
|| condition
== SWFDEC_EVENT_CHANGED
) {
256 SwfdecAsValue argv
[2];
257 SwfdecMovie
*movie
= SWFDEC_MOVIE (actor
);
259 if (condition
== SWFDEC_EVENT_SCROLL
)
260 SWFDEC_AS_VALUE_SET_STRING (&argv
[0], SWFDEC_AS_STR_onScroller
);
262 SWFDEC_AS_VALUE_SET_STRING (&argv
[0], SWFDEC_AS_STR_onChanged
);
263 SWFDEC_AS_VALUE_SET_MOVIE (&argv
[1], movie
);
264 swfdec_sandbox_use (movie
->resource
->sandbox
);
265 swfdec_as_relay_call (SWFDEC_AS_RELAY (actor
),
266 SWFDEC_AS_STR_broadcastMessage
, 2, argv
, NULL
);
267 swfdec_sandbox_unuse (movie
->resource
->sandbox
);
271 swfdec_sandbox_use (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
273 swfdec_event_list_execute (actor
->events
, swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (thisp
)),
276 /* FIXME: how do we compute the version correctly here? */
278 name
= swfdec_event_type_get_name (condition
);
280 swfdec_as_relay_call (SWFDEC_AS_RELAY (actor
), name
, 0, NULL
, NULL
);
282 if (condition
== SWFDEC_EVENT_CONSTRUCT
&& need_constructor
)
283 swfdec_as_relay_call (SWFDEC_AS_RELAY (thisp
), SWFDEC_AS_STR_constructor
, 0, NULL
, NULL
);
285 swfdec_sandbox_unuse (SWFDEC_MOVIE (actor
)->resource
->sandbox
);
289 * swfdec_actor_queue_script_with_key:
290 * @movie: a #SwfdecMovie
291 * @condition: the event that should happen
292 * @key: the key for this event
294 * Queues execution of all scripts associated with the given event and key.
297 swfdec_actor_queue_script_with_key (SwfdecActor
*actor
,
298 SwfdecEventType condition
, guint8 key
)
300 SwfdecPlayer
*player
;
303 g_return_if_fail (SWFDEC_IS_ACTOR (actor
));
305 if (!SWFDEC_IS_SPRITE_MOVIE (actor
) && !SWFDEC_IS_BUTTON_MOVIE (actor
))
307 /* can happen for mouse/keyboard events on the initial movie */
308 if (SWFDEC_MOVIE (actor
)->resource
->sandbox
== NULL
) {
309 SWFDEC_INFO ("movie %s not yet initialized, skipping event", SWFDEC_MOVIE (actor
)->name
);
314 case SWFDEC_EVENT_INITIALIZE
:
315 importance
= SWFDEC_PLAYER_ACTION_QUEUE_INIT
;
317 case SWFDEC_EVENT_CONSTRUCT
:
318 importance
= SWFDEC_PLAYER_ACTION_QUEUE_CONSTRUCT
;
320 case SWFDEC_EVENT_LOAD
:
321 case SWFDEC_EVENT_ENTER
:
322 case SWFDEC_EVENT_UNLOAD
:
323 case SWFDEC_EVENT_MOUSE_MOVE
:
324 case SWFDEC_EVENT_MOUSE_DOWN
:
325 case SWFDEC_EVENT_MOUSE_UP
:
326 case SWFDEC_EVENT_KEY_UP
:
327 case SWFDEC_EVENT_KEY_DOWN
:
328 case SWFDEC_EVENT_DATA
:
329 case SWFDEC_EVENT_PRESS
:
330 case SWFDEC_EVENT_RELEASE
:
331 case SWFDEC_EVENT_RELEASE_OUTSIDE
:
332 case SWFDEC_EVENT_ROLL_OVER
:
333 case SWFDEC_EVENT_ROLL_OUT
:
334 case SWFDEC_EVENT_DRAG_OVER
:
335 case SWFDEC_EVENT_DRAG_OUT
:
336 case SWFDEC_EVENT_KEY_PRESS
:
337 case SWFDEC_EVENT_CHANGED
:
338 case SWFDEC_EVENT_SCROLL
:
339 importance
= SWFDEC_PLAYER_ACTION_QUEUE_NORMAL
;
342 g_return_if_reached ();
345 player
= SWFDEC_PLAYER (swfdec_gc_object_get_context (actor
));
346 swfdec_player_add_action (player
, actor
, condition
, key
, importance
);
350 * swfdec_actor_queue_script:
351 * @movie: a #SwfdecMovie
352 * @condition: the event that should happen
354 * Queues execution of all scripts associated with the given event.
357 swfdec_actor_queue_script (SwfdecActor
*actor
, SwfdecEventType condition
)
359 swfdec_actor_queue_script_with_key (actor
, condition
, 0);
363 * swfdec_actor_get_mouse_events:
364 * @movie: a #SwfdecActor
366 * Checks if this actor should respond to mouse events.
368 * Returns: %TRUE if this movie can receive mouse events
371 swfdec_actor_get_mouse_events (SwfdecActor
*actor
)
373 SwfdecActorClass
*klass
;
375 g_return_val_if_fail (SWFDEC_IS_ACTOR (actor
), FALSE
);
377 klass
= SWFDEC_ACTOR_GET_CLASS (actor
);
378 if (klass
->mouse_events
)
379 return klass
->mouse_events (actor
);
385 swfdec_actor_has_focusrect (SwfdecActor
*actor
)
387 g_return_val_if_fail (SWFDEC_IS_ACTOR (actor
), FALSE
);
389 if (!SWFDEC_IS_BUTTON_MOVIE (actor
) &&
390 !SWFDEC_IS_SPRITE_MOVIE (actor
))
393 if (actor
->focusrect
== SWFDEC_FLASH_MAYBE
) {
394 actor
= SWFDEC_ACTOR (swfdec_movie_get_root (SWFDEC_MOVIE (actor
)));
396 g_assert (actor
->focusrect
!= SWFDEC_FLASH_MAYBE
);
398 return actor
->focusrect
!= SWFDEC_FLASH_NO
;