[Swfdec] 59 commits - libswfdec-gtk/swfdec_gtk_widget.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h libswfdec/swfdec_button.c libswfdec/swfdec_button.h libswfdec/swfdec_button_movie.c libswfdec/swfdec_button_movie.h libswfdec/swfdec_event.c libswfdec/swfdec_event.h libswfdec/swfdec_graphic_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_player.c libswfdec/swfdec_player.h libswfdec/swfdec_player_internal.h libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_sprite_movie_as.c libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_tag.c libswfdec/swfdec_types.h test/dump.c test/trace vivified/ui

Benjamin Otte company at kemper.freedesktop.org
Wed Nov 28 07:44:34 PST 2007


 libswfdec-gtk/swfdec_gtk_widget.c                       |   19 
 libswfdec/swfdec_as_object.c                            |   56 +-
 libswfdec/swfdec_as_object.h                            |    4 
 libswfdec/swfdec_button.c                               |  228 +++++++++
 libswfdec/swfdec_button.h                               |   10 
 libswfdec/swfdec_button_movie.c                         |  382 ++++++++--------
 libswfdec/swfdec_button_movie.h                         |    4 
 libswfdec/swfdec_event.c                                |   15 
 libswfdec/swfdec_event.h                                |    1 
 libswfdec/swfdec_graphic_movie.c                        |   12 
 libswfdec/swfdec_movie.c                                |  294 +++++++-----
 libswfdec/swfdec_movie.h                                |   64 +-
 libswfdec/swfdec_player.c                               |  253 +++++++---
 libswfdec/swfdec_player.h                               |   11 
 libswfdec/swfdec_player_internal.h                      |    4 
 libswfdec/swfdec_sprite.c                               |   20 
 libswfdec/swfdec_sprite.h                               |    3 
 libswfdec/swfdec_sprite_movie.c                         |   10 
 libswfdec/swfdec_sprite_movie_as.c                      |    2 
 libswfdec/swfdec_tag.c                                  |   74 ---
 libswfdec/swfdec_types.h                                |    1 
 test/dump.c                                             |   17 
 test/trace/Makefile.am                                  |   99 ++++
 test/trace/button-events-button-5.swf                   |binary
 test/trace/button-events-button-5.swf.act               |   17 
 test/trace/button-events-button-5.swf.trace             |   60 ++
 test/trace/button-events-button-6.swf                   |binary
 test/trace/button-events-button-6.swf.act               |   17 
 test/trace/button-events-button-6.swf.trace             |   68 ++
 test/trace/button-events-button-7.swf                   |binary
 test/trace/button-events-button-7.swf.act               |   17 
 test/trace/button-events-button-7.swf.trace             |   68 ++
 test/trace/button-events-button-8.swf                   |binary
 test/trace/button-events-button-8.swf.act               |   17 
 test/trace/button-events-button-8.swf.trace             |   68 ++
 test/trace/button-events-menu-5.swf                     |binary
 test/trace/button-events-menu-5.swf.act                 |   17 
 test/trace/button-events-menu-5.swf.trace               |   53 ++
 test/trace/button-events-menu-6.swf                     |binary
 test/trace/button-events-menu-6.swf.act                 |   17 
 test/trace/button-events-menu-6.swf.trace               |   60 ++
 test/trace/button-events-menu-7.swf                     |binary
 test/trace/button-events-menu-7.swf.act                 |   17 
 test/trace/button-events-menu-7.swf.trace               |   60 ++
 test/trace/button-events-menu-8.swf                     |binary
 test/trace/button-events-menu-8.swf.act                 |   17 
 test/trace/button-events-menu-8.swf.trace               |   60 ++
 test/trace/button-events.c                              |  144 ++++++
 test/trace/button-hittest-5.swf                         |binary
 test/trace/button-hittest-5.swf.act                     |   17 
 test/trace/button-hittest-5.swf.trace                   |    9 
 test/trace/button-hittest-6.swf                         |binary
 test/trace/button-hittest-6.swf.act                     |   17 
 test/trace/button-hittest-6.swf.trace                   |    9 
 test/trace/button-hittest-7.swf                         |binary
 test/trace/button-hittest-7.swf.act                     |   17 
 test/trace/button-hittest-7.swf.trace                   |    9 
 test/trace/button-hittest-8.swf                         |binary
 test/trace/button-hittest-8.swf.act                     |   17 
 test/trace/button-hittest-8.swf.trace                   |    9 
 test/trace/button-hittest.c                             |   85 +++
 test/trace/definebutton-5.swf                           |binary
 test/trace/definebutton-5.swf.act                       |   17 
 test/trace/definebutton-5.swf.trace                     |   18 
 test/trace/definebutton-6.swf                           |binary
 test/trace/definebutton-6.swf.act                       |   17 
 test/trace/definebutton-6.swf.trace                     |   18 
 test/trace/definebutton-7.swf                           |binary
 test/trace/definebutton-7.swf.act                       |   17 
 test/trace/definebutton-7.swf.trace                     |   18 
 test/trace/definebutton-8.swf                           |binary
 test/trace/definebutton-8.swf.act                       |   17 
 test/trace/definebutton-8.swf.trace                     |   18 
 test/trace/definebutton.xml                             |  138 +++++
 test/trace/mouse-addProperty-relevant-5.swf             |binary
 test/trace/mouse-addProperty-relevant-5.swf.act         |    9 
 test/trace/mouse-addProperty-relevant-5.swf.trace       |    1 
 test/trace/mouse-addProperty-relevant-6.swf             |binary
 test/trace/mouse-addProperty-relevant-6.swf.act         |    9 
 test/trace/mouse-addProperty-relevant-6.swf.trace       |    3 
 test/trace/mouse-addProperty-relevant-7.swf             |binary
 test/trace/mouse-addProperty-relevant-7.swf.act         |    9 
 test/trace/mouse-addProperty-relevant-7.swf.trace       |    3 
 test/trace/mouse-addProperty-relevant-8.swf             |binary
 test/trace/mouse-addProperty-relevant-8.swf.act         |    9 
 test/trace/mouse-addProperty-relevant-8.swf.trace       |    3 
 test/trace/mouse-addProperty-relevant.as                |   23 
 test/trace/mouse-movie-below-movie-5.swf                |binary
 test/trace/mouse-movie-below-movie-5.swf.act            |   17 
 test/trace/mouse-movie-below-movie-6.swf                |binary
 test/trace/mouse-movie-below-movie-6.swf.act            |   17 
 test/trace/mouse-movie-below-movie-6.swf.trace          |    9 
 test/trace/mouse-movie-below-movie-7.swf                |binary
 test/trace/mouse-movie-below-movie-7.swf.act            |   17 
 test/trace/mouse-movie-below-movie-7.swf.trace          |    9 
 test/trace/mouse-movie-below-movie-8.swf                |binary
 test/trace/mouse-movie-below-movie-8.swf.act            |   17 
 test/trace/mouse-movie-below-movie-8.swf.trace          |    9 
 test/trace/mouse-movie-below-movie.as                   |   27 +
 test/trace/mouse-movie-below-nonevent-movie-5.swf       |binary
 test/trace/mouse-movie-below-nonevent-movie-5.swf.act   |   17 
 test/trace/mouse-movie-below-nonevent-movie-6.swf       |binary
 test/trace/mouse-movie-below-nonevent-movie-6.swf.act   |   17 
 test/trace/mouse-movie-below-nonevent-movie-6.swf.trace |    5 
 test/trace/mouse-movie-below-nonevent-movie-7.swf       |binary
 test/trace/mouse-movie-below-nonevent-movie-7.swf.act   |   17 
 test/trace/mouse-movie-below-nonevent-movie-7.swf.trace |    5 
 test/trace/mouse-movie-below-nonevent-movie-8.swf       |binary
 test/trace/mouse-movie-below-nonevent-movie-8.swf.act   |   17 
 test/trace/mouse-movie-below-nonevent-movie-8.swf.trace |    5 
 test/trace/mouse-movie-below-nonevent-movie.as          |   27 +
 test/trace/onUnload-prototype-5.swf                     |binary
 test/trace/onUnload-prototype-5.swf.trace               |    4 
 test/trace/onUnload-prototype-6.swf                     |binary
 test/trace/onUnload-prototype-6.swf.trace               |    4 
 test/trace/onUnload-prototype-7.swf                     |binary
 test/trace/onUnload-prototype-7.swf.trace               |    4 
 test/trace/onUnload-prototype-8.swf                     |binary
 test/trace/onUnload-prototype-8.swf.trace               |    4 
 test/trace/onUnload-prototype.as                        |   17 
 test/trace/swfdec_interaction.c                         |   23 
 vivified/ui/Makefile.am                                 |    4 
 vivified/ui/vivi_widget.c                               |    9 
 123 files changed, 2609 insertions(+), 588 deletions(-)

New commits:
commit 6b42d7a154bc54f013414e87ff410747a584644d
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 16:19:07 2007 +0100

    add a test for hit tests on buttons

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 45159ee..1a40a31 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -315,6 +315,19 @@ EXTRA_DIST = \
 	button-events-menu-8.swf \
 	button-events-menu-8.swf.act \
 	button-events-menu-8.swf.trace \
+	button-hittest-5.swf \
+	button-hittest-5.swf.act \
+	button-hittest-5.swf.trace \
+	button-hittest-6.swf \
+	button-hittest-6.swf.act \
+	button-hittest-6.swf.trace \
+	button-hittest-7.swf \
+	button-hittest-7.swf.act \
+	button-hittest-7.swf.trace \
+	button-hittest-8.swf \
+	button-hittest-8.swf.act \
+	button-hittest-8.swf.trace \
+	button-hittest.c \
 	button-properties.as \
 	button-properties-5.swf \
 	button-properties-5.swf.trace \
diff --git a/test/trace/button-hittest-5.swf b/test/trace/button-hittest-5.swf
new file mode 100644
index 0000000..18ace29
Binary files /dev/null and b/test/trace/button-hittest-5.swf differ
diff --git a/test/trace/button-hittest-5.swf.act b/test/trace/button-hittest-5.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-hittest-5.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-hittest-5.swf.trace b/test/trace/button-hittest-5.swf.trace
new file mode 100644
index 0000000..c91a351
--- /dev/null
+++ b/test/trace/button-hittest-5.swf.trace
@@ -0,0 +1,9 @@
+button Idle => OverUp: _level0
+button OverUp => OverDown: _level0
+button OverDown => OutDown: _level0
+button OutDown => OverDown: _level0
+button OverDown => OverUp: _level0
+button OverUp => OverDown: _level0
+button OverDown => OutDown: _level0
+button OutDown => Idle: _level0
+button Idle => OverUp: _level0
diff --git a/test/trace/button-hittest-6.swf b/test/trace/button-hittest-6.swf
new file mode 100644
index 0000000..b2bf0ec
Binary files /dev/null and b/test/trace/button-hittest-6.swf differ
diff --git a/test/trace/button-hittest-6.swf.act b/test/trace/button-hittest-6.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-hittest-6.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-hittest-6.swf.trace b/test/trace/button-hittest-6.swf.trace
new file mode 100644
index 0000000..ed871dc
--- /dev/null
+++ b/test/trace/button-hittest-6.swf.trace
@@ -0,0 +1,9 @@
+button Idle => OverUp: _level0.instance1
+button OverUp => OverDown: _level0.instance1
+button OverDown => OutDown: _level0.instance1
+button OutDown => OverDown: _level0.instance1
+button OverDown => OverUp: _level0.instance1
+button OverUp => OverDown: _level0.instance1
+button OverDown => OutDown: _level0.instance1
+button OutDown => Idle: _level0.instance1
+button Idle => OverUp: _level0
diff --git a/test/trace/button-hittest-7.swf b/test/trace/button-hittest-7.swf
new file mode 100644
index 0000000..9646812
Binary files /dev/null and b/test/trace/button-hittest-7.swf differ
diff --git a/test/trace/button-hittest-7.swf.act b/test/trace/button-hittest-7.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-hittest-7.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-hittest-7.swf.trace b/test/trace/button-hittest-7.swf.trace
new file mode 100644
index 0000000..ed871dc
--- /dev/null
+++ b/test/trace/button-hittest-7.swf.trace
@@ -0,0 +1,9 @@
+button Idle => OverUp: _level0.instance1
+button OverUp => OverDown: _level0.instance1
+button OverDown => OutDown: _level0.instance1
+button OutDown => OverDown: _level0.instance1
+button OverDown => OverUp: _level0.instance1
+button OverUp => OverDown: _level0.instance1
+button OverDown => OutDown: _level0.instance1
+button OutDown => Idle: _level0.instance1
+button Idle => OverUp: _level0
diff --git a/test/trace/button-hittest-8.swf b/test/trace/button-hittest-8.swf
new file mode 100644
index 0000000..af501e5
Binary files /dev/null and b/test/trace/button-hittest-8.swf differ
diff --git a/test/trace/button-hittest-8.swf.act b/test/trace/button-hittest-8.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-hittest-8.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-hittest-8.swf.trace b/test/trace/button-hittest-8.swf.trace
new file mode 100644
index 0000000..ed871dc
--- /dev/null
+++ b/test/trace/button-hittest-8.swf.trace
@@ -0,0 +1,9 @@
+button Idle => OverUp: _level0.instance1
+button OverUp => OverDown: _level0.instance1
+button OverDown => OutDown: _level0.instance1
+button OutDown => OverDown: _level0.instance1
+button OverDown => OverUp: _level0.instance1
+button OverUp => OverDown: _level0.instance1
+button OverDown => OutDown: _level0.instance1
+button OutDown => Idle: _level0.instance1
+button Idle => OverUp: _level0
diff --git a/test/trace/button-hittest.c b/test/trace/button-hittest.c
new file mode 100644
index 0000000..9cb574e
--- /dev/null
+++ b/test/trace/button-hittest.c
@@ -0,0 +1,85 @@
+/* gcc `pkg-config --libs --cflags libming` button-hittest.c -o button-hittest && ./button-hittest
+ */
+
+#include <ming.h>
+
+static const char *button_events[] = { "Idle => OverUp", "OverUp => Idle", "OverUp => OverDown", "OverDown => OverUp", "OverDown => OutDown", "OutDown => OverDown", "OutDown => Idle", "Idle => OutDown", "OverDown => Idle" };
+
+static void
+add_button_events (SWFButton button)
+{
+  char script[100];
+  unsigned int i;
+
+  for (i = 0; i < sizeof (button_events) / sizeof (button_events[0]); i++) {
+    sprintf (script, "trace (\"button %s: \" + this);", button_events[i]);
+    SWFButton_addAction (button, newSWFAction (script), (1 << i));
+  }
+}
+
+static SWFCharacter
+get_rectangle (int r, int g, int b)
+{
+  SWFShape shape;
+  SWFFillStyle fill;
+
+  shape = newSWFShape ();
+  fill = SWFShape_addSolidFillStyle (shape, r, g, b, 255);
+  SWFShape_setRightFillStyle (shape, fill);
+  SWFShape_drawLineTo (shape, 100, 0);
+  SWFShape_drawLineTo (shape, 100, 100);
+  SWFShape_drawLineTo (shape, 0, 100);
+  SWFShape_drawLineTo (shape, 0, 0);
+
+  return (SWFCharacter) shape;
+}
+
+static void
+do_movie (int version)
+{
+  char name[100];
+  SWFMovie movie;
+  SWFDisplayItem item;
+  SWFButton button, button2;
+  SWFButtonRecord rec;
+
+  movie = newSWFMovieWithVersion (version);
+  SWFMovie_setRate (movie, 10);
+  SWFMovie_setDimension (movie, 200, 150);
+
+  button = newSWFButton ();
+  add_button_events (button);
+  rec = SWFButton_addCharacter (button, get_rectangle (255, 0, 0), SWFBUTTON_HIT);
+  SWFButtonRecord_setDepth (rec, 42);
+  SWFButtonRecord_moveTo (rec, 40, 40);
+  SWFButtonRecord_scaleTo (rec, 0.5, 0.5);
+
+  button2 = newSWFButton ();
+  SWFButton_setMenu (button2, 1);
+  add_button_events (button2);
+  rec = SWFButton_addCharacter (button2, get_rectangle (0, 255, 0), SWFBUTTON_HIT);
+  SWFButtonRecord_scaleTo (rec, 2, 1.5);
+  rec = SWFButton_addCharacter (button2, (SWFCharacter) button, SWFBUTTON_UP | SWFBUTTON_OVER | SWFBUTTON_DOWN);
+
+  item = SWFMovie_add (movie, button2);
+
+  SWFMovie_nextFrame (movie);
+
+  sprintf (name, "button-hittest-%d.swf", version);
+  SWFMovie_save (movie, name);
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+
+  if (Ming_init ())
+    return 1;
+
+  for (i = 8; i >= 5; i--) {
+    do_movie (i);
+  }
+
+  return 0;
+}
commit 930931b307fc143faa5b98e04cc7b68a9a3bba9d
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 16:16:03 2007 +0100

    in Flash 5, the this object for button events was a MovieClip

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 33717b0..657b519 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -424,6 +424,10 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
     if (condition == SWFDEC_EVENT_CONSTRUCT || condition < SWFDEC_EVENT_PRESS)
       return;
     thisp = SWFDEC_AS_OBJECT (movie->parent);
+    if (swfdec_movie_get_version (movie) <= 5) {
+      while (!SWFDEC_IS_SPRITE_MOVIE (thisp))
+	thisp = SWFDEC_AS_OBJECT (SWFDEC_MOVIE (thisp)->parent);
+    }
     g_assert (thisp);
   } else {
     thisp = SWFDEC_AS_OBJECT (movie);
commit fb326d9f0c90c8e3edb2aba66c1ac0ad12a6f6f4
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 15:31:02 2007 +0100

    remove g_print

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index a36d7e9..471b936 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -69,8 +69,6 @@ swfdec_button_create_movie (SwfdecGraphic *graphic, gsize *size)
 
   movie->button = g_object_ref (button);
   *size = sizeof (SwfdecButtonMovie);
-  g_print ("extents: %g %g  %g %g\n", graphic->extents.x0, graphic->extents.y0,
-      graphic->extents.x1, graphic->extents.y1);
   if (button->events)
     SWFDEC_MOVIE (movie)->events = swfdec_event_list_copy (button->events);
 
commit 90003ff936f9e42fe86d69c4c58a57cab12731ed
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 15:24:43 2007 +0100

    use the right matrix to compute the extents
    
    I should stop guessing about reverse or not reverse when applying matrices

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 15b3c89..a36d7e9 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -69,6 +69,8 @@ swfdec_button_create_movie (SwfdecGraphic *graphic, gsize *size)
 
   movie->button = g_object_ref (button);
   *size = sizeof (SwfdecButtonMovie);
+  g_print ("extents: %g %g  %g %g\n", graphic->extents.x0, graphic->extents.y0,
+      graphic->extents.x1, graphic->extents.y1);
   if (button->events)
     SWFDEC_MOVIE (movie)->events = swfdec_event_list_copy (button->events);
 
@@ -141,7 +143,7 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
   while (swfdec_bits_peek_u8 (&bits)) {
     SwfdecBits tmp;
     SwfdecBuffer *buffer;
-    cairo_matrix_t trans, inverse;
+    cairo_matrix_t trans;
     SwfdecColorTransform ctrans;
     guint states, gid;
     gboolean has_blend_mode, has_filters;
@@ -172,7 +174,7 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
         states & (1 << SWFDEC_BUTTON_OVER) ? "OVER " : "",
 	states & (1 << SWFDEC_BUTTON_UP) ? "UP " : "");
 
-    swfdec_bits_get_matrix (&bits, &trans, &inverse);
+    swfdec_bits_get_matrix (&bits, &trans, NULL);
     SWFDEC_LOG ("matrix: %g %g  %g %g   %g %g",
 	trans.xx, trans.yy, 
 	trans.xy, trans.yx,
@@ -196,7 +198,7 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
       SwfdecGraphic *graphic = swfdec_swf_decoder_get_character (s, gid);
       if (SWFDEC_IS_GRAPHIC (graphic)) {
 	SwfdecRect rect;
-	swfdec_rect_transform (&rect, &graphic->extents, &inverse);
+	swfdec_rect_transform (&rect, &graphic->extents, &trans);
 	swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents, &SWFDEC_GRAPHIC (button)->extents, &rect);
       } else {
 	SWFDEC_ERROR ("graphic for id %u not found", gid);
@@ -255,14 +257,14 @@ tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
   while (swfdec_bits_peek_u8 (&s->b)) {
     SwfdecBits tmp;
     SwfdecBuffer *buffer;
-    cairo_matrix_t matrix, inverse;
+    cairo_matrix_t matrix;
     guint gid;
 
     tmp = s->b;
     flags = swfdec_bits_get_u8 (&tmp);
     gid = swfdec_bits_get_u16 (&tmp);
     swfdec_bits_get_u16 (&tmp);
-    swfdec_bits_get_matrix (&tmp, &matrix, &inverse);
+    swfdec_bits_get_matrix (&tmp, &matrix, NULL);
     buffer = swfdec_bits_get_buffer (&s->b, (swfdec_bits_left (&s->b) - swfdec_bits_left (&tmp)) / 8);
     if (buffer == NULL)
       break;
@@ -272,7 +274,7 @@ tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
       SwfdecGraphic *graphic = swfdec_swf_decoder_get_character (s, gid);
       if (SWFDEC_IS_GRAPHIC (graphic)) {
 	SwfdecRect rect;
-	swfdec_rect_transform (&rect, &graphic->extents, &inverse);
+	swfdec_rect_transform (&rect, &graphic->extents, &matrix);
 	swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents, &SWFDEC_GRAPHIC (button)->extents, &rect);
       } else {
 	SWFDEC_ERROR ("graphic for id %u not found", gid);
commit 695927c3c35acee82f17b2e45e9f9a5541c2090a
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 15:07:54 2007 +0100

    character id comes before depth, not vice versa

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 6e3e637..15b3c89 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -163,8 +163,8 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
       SWFDEC_LOG ("  reserved = %d", reserved);
     }
     states = swfdec_bits_getbits (&bits, 4);
-    swfdec_bits_get_u16 (&bits);
     gid = swfdec_bits_get_u16 (&bits);
+    swfdec_bits_get_u16 (&bits);
 
     SWFDEC_LOG ("  states: %s%s%s%s",
         states & (1 << SWFDEC_BUTTON_HIT) ? "HIT " : "", 
@@ -260,8 +260,8 @@ tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
 
     tmp = s->b;
     flags = swfdec_bits_get_u8 (&tmp);
-    swfdec_bits_get_u16 (&tmp);
     gid = swfdec_bits_get_u16 (&tmp);
+    swfdec_bits_get_u16 (&tmp);
     swfdec_bits_get_matrix (&tmp, &matrix, &inverse);
     buffer = swfdec_bits_get_buffer (&s->b, (swfdec_bits_left (&s->b) - swfdec_bits_left (&tmp)) / 8);
     if (buffer == NULL)
diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 4395c2e..1c9e1e3 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -248,11 +248,13 @@ swfdec_button_movie_hit_test (SwfdecButtonMovie *button, double x, double y)
     if ((swfdec_bits_get_u8 (&bits) & (1 << SWFDEC_BUTTON_HIT)) == 0)
       continue;
 
-    swfdec_bits_get_u16 (&bits); /* depth */
     id = swfdec_bits_get_u16 (&bits);
+    swfdec_bits_get_u16 (&bits); /* depth */
     graphic = swfdec_swf_decoder_get_character (dec, id);
-    if (!SWFDEC_IS_GRAPHIC (graphic))
+    if (!SWFDEC_IS_GRAPHIC (graphic)) {
+      SWFDEC_ERROR ("id %u is no graphic", id);
       continue;
+    }
     tmpx = x;
     tmpy = y;
     swfdec_bits_get_matrix (&bits, &matrix, &inverse);
commit e8502cb92ba87686404b9981df550dfbe536a6e3
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 13:39:17 2007 +0100

    add a test for the DefineButton tag

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 6eef89d..45159ee 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -629,6 +629,19 @@ EXTRA_DIST = \
 	date-properties-7.swf.trace \
 	date-properties-8.swf \
 	date-properties-8.swf.trace \
+	definebutton-5.swf \
+	definebutton-5.swf.act \
+	definebutton-5.swf.trace \
+	definebutton-6.swf \
+	definebutton-6.swf.act \
+	definebutton-6.swf.trace \
+	definebutton-7.swf \
+	definebutton-7.swf.act \
+	definebutton-7.swf.trace \
+	definebutton-8.swf \
+	definebutton-8.swf.act \
+	definebutton-8.swf.trace \
+	definebutton.xml \
 	definefunction2-arguments.swf \
 	definefunction2-arguments.swf.trace \
 	definefunction2-arguments.xml \
diff --git a/test/trace/definebutton-5.swf b/test/trace/definebutton-5.swf
new file mode 100644
index 0000000..6ab33d2
Binary files /dev/null and b/test/trace/definebutton-5.swf differ
diff --git a/test/trace/definebutton-5.swf.act b/test/trace/definebutton-5.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/definebutton-5.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/definebutton-5.swf.trace b/test/trace/definebutton-5.swf.trace
new file mode 100644
index 0000000..49d341d
--- /dev/null
+++ b/test/trace/definebutton-5.swf.trace
@@ -0,0 +1,18 @@
+load _level0.instance1.instance2.instance3
+unload _level0.instance1.instance2.instance3
+load _level0.instance1.instance4.instance5
+unload _level0.instance1.instance4.instance5
+load _level0.instance1.instance6.instance7
+unload _level0.instance1.instance6.instance7
+load _level0.instance1.instance8.instance9
+unload _level0.instance1.instance8.instance9
+load _level0.instance1.instance10.instance11
+unload _level0.instance1.instance10.instance11
+load _level0.instance1.instance12.instance13
+_level0
+unload _level0.instance1.instance12.instance13
+load _level0.instance1.instance14.instance15
+unload _level0.instance1.instance14.instance15
+load _level0.instance1.instance16.instance17
+unload _level0.instance1.instance16.instance17
+load _level0.instance1.instance18.instance19
diff --git a/test/trace/definebutton-6.swf b/test/trace/definebutton-6.swf
new file mode 100644
index 0000000..6e1444b
Binary files /dev/null and b/test/trace/definebutton-6.swf differ
diff --git a/test/trace/definebutton-6.swf.act b/test/trace/definebutton-6.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/definebutton-6.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/definebutton-6.swf.trace b/test/trace/definebutton-6.swf.trace
new file mode 100644
index 0000000..49d341d
--- /dev/null
+++ b/test/trace/definebutton-6.swf.trace
@@ -0,0 +1,18 @@
+load _level0.instance1.instance2.instance3
+unload _level0.instance1.instance2.instance3
+load _level0.instance1.instance4.instance5
+unload _level0.instance1.instance4.instance5
+load _level0.instance1.instance6.instance7
+unload _level0.instance1.instance6.instance7
+load _level0.instance1.instance8.instance9
+unload _level0.instance1.instance8.instance9
+load _level0.instance1.instance10.instance11
+unload _level0.instance1.instance10.instance11
+load _level0.instance1.instance12.instance13
+_level0
+unload _level0.instance1.instance12.instance13
+load _level0.instance1.instance14.instance15
+unload _level0.instance1.instance14.instance15
+load _level0.instance1.instance16.instance17
+unload _level0.instance1.instance16.instance17
+load _level0.instance1.instance18.instance19
diff --git a/test/trace/definebutton-7.swf b/test/trace/definebutton-7.swf
new file mode 100644
index 0000000..067ce1a
Binary files /dev/null and b/test/trace/definebutton-7.swf differ
diff --git a/test/trace/definebutton-7.swf.act b/test/trace/definebutton-7.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/definebutton-7.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/definebutton-7.swf.trace b/test/trace/definebutton-7.swf.trace
new file mode 100644
index 0000000..49d341d
--- /dev/null
+++ b/test/trace/definebutton-7.swf.trace
@@ -0,0 +1,18 @@
+load _level0.instance1.instance2.instance3
+unload _level0.instance1.instance2.instance3
+load _level0.instance1.instance4.instance5
+unload _level0.instance1.instance4.instance5
+load _level0.instance1.instance6.instance7
+unload _level0.instance1.instance6.instance7
+load _level0.instance1.instance8.instance9
+unload _level0.instance1.instance8.instance9
+load _level0.instance1.instance10.instance11
+unload _level0.instance1.instance10.instance11
+load _level0.instance1.instance12.instance13
+_level0
+unload _level0.instance1.instance12.instance13
+load _level0.instance1.instance14.instance15
+unload _level0.instance1.instance14.instance15
+load _level0.instance1.instance16.instance17
+unload _level0.instance1.instance16.instance17
+load _level0.instance1.instance18.instance19
diff --git a/test/trace/definebutton-8.swf b/test/trace/definebutton-8.swf
new file mode 100644
index 0000000..7a445b7
Binary files /dev/null and b/test/trace/definebutton-8.swf differ
diff --git a/test/trace/definebutton-8.swf.act b/test/trace/definebutton-8.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/definebutton-8.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/definebutton-8.swf.trace b/test/trace/definebutton-8.swf.trace
new file mode 100644
index 0000000..49d341d
--- /dev/null
+++ b/test/trace/definebutton-8.swf.trace
@@ -0,0 +1,18 @@
+load _level0.instance1.instance2.instance3
+unload _level0.instance1.instance2.instance3
+load _level0.instance1.instance4.instance5
+unload _level0.instance1.instance4.instance5
+load _level0.instance1.instance6.instance7
+unload _level0.instance1.instance6.instance7
+load _level0.instance1.instance8.instance9
+unload _level0.instance1.instance8.instance9
+load _level0.instance1.instance10.instance11
+unload _level0.instance1.instance10.instance11
+load _level0.instance1.instance12.instance13
+_level0
+unload _level0.instance1.instance12.instance13
+load _level0.instance1.instance14.instance15
+unload _level0.instance1.instance14.instance15
+load _level0.instance1.instance16.instance17
+unload _level0.instance1.instance16.instance17
+load _level0.instance1.instance18.instance19
diff --git a/test/trace/definebutton.xml b/test/trace/definebutton.xml
new file mode 100644
index 0000000..e07514d
--- /dev/null
+++ b/test/trace/definebutton.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0"?>
+<swf version="8" compressed="0">
+  <Header framerate="1" frames="1">
+    <size>
+      <Rectangle left="0" right="4000" top="0" bottom="3000"/>
+    </size>
+    <tags>
+      <SetBackgroundColor>
+        <color>
+          <Color red="255" green="255" blue="255"/>
+        </color>
+      </SetBackgroundColor>
+      <DefineShape objectID="1">
+        <bounds>
+          <Rectangle left="0" right="1200" top="0" bottom="1200"/>
+        </bounds>
+        <styles>
+          <StyleList>
+            <fillStyles>
+              <Solid>
+                <color>
+                  <Color red="255" green="0" blue="0"/>
+                </color>
+              </Solid>
+	    </fillStyles>
+	    <lineStyles />
+          </StyleList>
+        </styles>
+        <shapes>
+          <Shape>
+            <edges>
+              <ShapeSetup x="0" y="0" fillStyle1="1"/>
+              <LineTo x="0" y="1200"/>
+              <LineTo x="1200" y="0"/>
+              <LineTo x="0" y="-1200"/>
+              <LineTo x="-1200" y="0"/>
+              <ShapeSetup/>
+            </edges>
+          </Shape>
+        </shapes>
+      </DefineShape>
+      <DefineSprite objectID="2" frames="1">
+        <tags>
+	  <PlaceObject2 replace="0" depth="1" objectID="1" />
+	  <ShowFrame/>
+	</tags>
+      </DefineSprite>
+      <DefineSprite objectID="3" frames="1">
+        <tags>
+	  <PlaceObject2 replace="0" depth="1" objectID="2" allflags1="5" allflags2="0">
+	    <events>
+	      <Event flags1="1" flags2="0">
+		<actions>
+		  <Dictionary>
+		    <strings>
+		      <String value="load "/>
+		      <String value="this"/>
+		    </strings>
+		  </Dictionary>
+		  <PushData>
+		    <items>
+		      <StackDictionaryLookup index="0"/>
+		      <StackDictionaryLookup index="1"/>
+		    </items>
+		  </PushData>
+		  <GetVariable/>
+		  <AddTyped/>
+		  <Trace/>
+		  <EndAction/>
+		</actions>
+	      </Event>
+	      <Event flags1="4" flags2="0">
+		<actions>
+		  <Dictionary>
+		    <strings>
+		      <String value="unload "/>
+		      <String value="this"/>
+		    </strings>
+		  </Dictionary>
+		  <PushData>
+		    <items>
+		      <StackDictionaryLookup index="0"/>
+		      <StackDictionaryLookup index="1"/>
+		    </items>
+		  </PushData>
+		  <GetVariable/>
+		  <AddTyped/>
+		  <Trace/>
+		  <EndAction/>
+		</actions>
+	      </Event>
+	      <Event flags1="0" flags2="0"/>
+	    </events>
+	  </PlaceObject2>
+	  <ShowFrame/>
+	</tags>
+      </DefineSprite>
+      <DefineButton objectID="4">
+        <buttons>
+          <Button hitTest="0" down="0" over="0" up="1" objectID="3" depth="1">
+            <transform>
+              <Transform transX="1200" transY="0"/>
+            </transform>
+          </Button>
+          <Button hitTest="0" down="0" over="1" up="0" objectID="3" depth="1">
+            <transform>
+              <Transform transX="1200" transY="1200"/>
+            </transform>
+          </Button>
+          <Button hitTest="0" down="1" over="0" up="0" objectID="3" depth="1">
+            <transform>
+              <Transform transX="0" transY="1200"/>
+            </transform>
+          </Button>
+          <Button hitTest="1" down="0" over="0" up="0" objectID="1" depth="1">
+            <transform>
+              <Transform transX="0" transY="0"/>
+            </transform>
+          </Button>
+          <Button hitTest="0" down="0" over="0" up="0"/>
+	</buttons>
+        <actions>
+	  <PushData>
+	    <items>
+	      <StackString value="this"/>
+	    </items>
+	  </PushData>
+	  <GetVariable/>
+	  <Trace/>
+          <EndAction/>
+        </actions>
+      </DefineButton>
+      <PlaceObject2 replace="0" depth="1" objectID="4" />
+      <ShowFrame/>
+      <End/>
+    </tags>
+  </Header>
+</swf>
commit d49dd06bc9fad2d3522eba7fb1b5aad552a35bfc
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 13:35:25 2007 +0100

    movies on top of other movies need to receive events

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 0a8a50c..4395c2e 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -273,7 +273,7 @@ swfdec_button_movie_contains (SwfdecMovie *movie, double x, double y, gboolean e
     /* check for movies in a higher layer that react to events */
     SwfdecMovie *ret;
     ret = SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->contains (movie, x, y, TRUE);
-    if (ret && ret != movie)
+    if (ret && ret != movie && swfdec_movie_get_mouse_events (ret))
       return ret;
   }
   
commit a3f0a1265a9d5b4164c7a16645952c5333d85123
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 11:51:15 2007 +0100

    implement contains()

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 3ceae26..0a8a50c 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -229,46 +229,56 @@ swfdec_button_movie_init_movie (SwfdecMovie *mov)
   swfdec_button_movie_set_state (movie, SWFDEC_BUTTON_UP);
 }
 
-#if 0
-static gboolean G_GNUC_UNUSED
-swfdec_button_movie_mouse_in (SwfdecMovie *movie, double x, double y)
+static gboolean
+swfdec_button_movie_hit_test (SwfdecButtonMovie *button, double x, double y)
 {
-  GList *walk;
+  SwfdecSwfDecoder *dec;
+  GSList *walk;
   double tmpx, tmpy;
-  SwfdecButton *button = SWFDEC_BUTTON_MOVIE (movie)->button;
-  SwfdecContent *content;
 
-  for (walk = button->records; walk; walk = walk->next) {
-    cairo_matrix_t inverse;
-    content = walk->data;
-    if (content->end <= SWFDEC_BUTTON_HIT)
+  dec = SWFDEC_SWF_DECODER (SWFDEC_MOVIE (button)->resource->decoder);
+  for (walk = button->button->records; walk; walk = walk->next) {
+    SwfdecGraphic *graphic;
+    SwfdecBits bits;
+    cairo_matrix_t matrix, inverse;
+    guint id;
+
+    swfdec_bits_init (&bits, walk->data);
+
+    if ((swfdec_bits_get_u8 (&bits) & (1 << SWFDEC_BUTTON_HIT)) == 0)
+      continue;
+
+    swfdec_bits_get_u16 (&bits); /* depth */
+    id = swfdec_bits_get_u16 (&bits);
+    graphic = swfdec_swf_decoder_get_character (dec, id);
+    if (!SWFDEC_IS_GRAPHIC (graphic))
       continue;
     tmpx = x;
     tmpy = y;
-    swfdec_matrix_ensure_invertible (&content->transform, &inverse);
+    swfdec_bits_get_matrix (&bits, &matrix, &inverse);
     cairo_matrix_transform_point (&inverse, &tmpx, &tmpy);
 
     SWFDEC_LOG ("Checking button contents at %g %g (transformed from %g %g)", tmpx, tmpy, x, y);
-    if (swfdec_graphic_mouse_in (content->graphic, tmpx, tmpy))
+    if (swfdec_graphic_mouse_in (graphic, tmpx, tmpy))
       return TRUE;
     SWFDEC_LOG ("  missed");
   }
   return FALSE;
 }
 
-static void G_GNUC_UNUSED
-swfdec_button_movie_mouse_change (SwfdecMovie *mov, double x, double y, 
-    gboolean mouse_in, int button)
+static SwfdecMovie *
+swfdec_button_movie_contains (SwfdecMovie *movie, double x, double y, gboolean events)
 {
-  SwfdecButtonMovie *movie = SWFDEC_BUTTON_MOVIE (mov);
-  SwfdecButtonState new_state = swfdec_button_movie_get_state (movie, mouse_in, button);
-
-  if (new_state != movie->state) {
-    swfdec_button_movie_change_state (movie, new_state);
+  if (events) {
+    /* check for movies in a higher layer that react to events */
+    SwfdecMovie *ret;
+    ret = SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->contains (movie, x, y, TRUE);
+    if (ret && ret != movie)
+      return ret;
   }
-  swfdec_button_movie_change_mouse (movie, mouse_in, button);
+  
+  return swfdec_button_movie_hit_test (SWFDEC_BUTTON_MOVIE (movie), x, y) ? movie : NULL;
 }
-#endif
 
 static void
 swfdec_button_movie_dispose (GObject *object)
@@ -291,6 +301,7 @@ swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
   object_class->dispose = swfdec_button_movie_dispose;
   movie_class->init_movie = swfdec_button_movie_init_movie;
   movie_class->update_extents = swfdec_button_movie_update_extents;
+  movie_class->contains = swfdec_button_movie_contains;
 
   movie_class->mouse_events = swfdec_button_movie_mouse_events;
   movie_class->mouse_in = swfdec_button_movie_mouse_in;
commit a29b71f8b714793489a9226319781acc9b7c07dc
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 11:50:56 2007 +0100

    implement DefineButton and put hit state movies into the button's extents

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 3cbfb7a..6e3e637 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -141,9 +141,9 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
   while (swfdec_bits_peek_u8 (&bits)) {
     SwfdecBits tmp;
     SwfdecBuffer *buffer;
-    cairo_matrix_t trans;
+    cairo_matrix_t trans, inverse;
     SwfdecColorTransform ctrans;
-    guint states;
+    guint states, gid;
     gboolean has_blend_mode, has_filters;
 
     /* we parse the placement info into buffers each containing one palcement */
@@ -163,7 +163,8 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
       SWFDEC_LOG ("  reserved = %d", reserved);
     }
     states = swfdec_bits_getbits (&bits, 4);
-    swfdec_bits_skip_bytes (&bits, 4);
+    swfdec_bits_get_u16 (&bits);
+    gid = swfdec_bits_get_u16 (&bits);
 
     SWFDEC_LOG ("  states: %s%s%s%s",
         states & (1 << SWFDEC_BUTTON_HIT) ? "HIT " : "", 
@@ -171,7 +172,7 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
         states & (1 << SWFDEC_BUTTON_OVER) ? "OVER " : "",
 	states & (1 << SWFDEC_BUTTON_UP) ? "UP " : "");
 
-    swfdec_bits_get_matrix (&bits, &trans, NULL);
+    swfdec_bits_get_matrix (&bits, &trans, &inverse);
     SWFDEC_LOG ("matrix: %g %g  %g %g   %g %g",
 	trans.xx, trans.yy, 
 	trans.xy, trans.yx,
@@ -187,8 +188,20 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
       SWFDEC_LOG ("  blend mode = %u", blend_mode);
     }
     buffer = swfdec_bits_get_buffer (&tmp, (swfdec_bits_left (&tmp) - swfdec_bits_left (&bits)) / 8);
-    g_assert (buffer);
+    if (buffer == NULL)
+      break;
     button->records = g_slist_prepend (button->records, buffer);
+    /* add hit state movies to button's extents */
+    if (states & (1 << SWFDEC_BUTTON_HIT)) {
+      SwfdecGraphic *graphic = swfdec_swf_decoder_get_character (s, gid);
+      if (SWFDEC_IS_GRAPHIC (graphic)) {
+	SwfdecRect rect;
+	swfdec_rect_transform (&rect, &graphic->extents, &inverse);
+	swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents, &SWFDEC_GRAPHIC (button)->extents, &rect);
+      } else {
+	SWFDEC_ERROR ("graphic for id %u not found", gid);
+      }
+    }
   }
   swfdec_bits_get_u8 (&bits);
   if (swfdec_bits_left (&bits)) {
@@ -229,7 +242,60 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
 int
 tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
 {
-  SWFDEC_ERROR ("implement DefineButton again");
+  guint id, flags;
+  SwfdecButton *button;
+
+  id = swfdec_bits_get_u16 (&s->b);
+  button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
+  if (!button)
+    return SWFDEC_STATUS_OK;
+
+  SWFDEC_LOG ("  ID: %d", id);
+
+  while (swfdec_bits_peek_u8 (&s->b)) {
+    SwfdecBits tmp;
+    SwfdecBuffer *buffer;
+    cairo_matrix_t matrix, inverse;
+    guint gid;
+
+    tmp = s->b;
+    flags = swfdec_bits_get_u8 (&tmp);
+    swfdec_bits_get_u16 (&tmp);
+    gid = swfdec_bits_get_u16 (&tmp);
+    swfdec_bits_get_matrix (&tmp, &matrix, &inverse);
+    buffer = swfdec_bits_get_buffer (&s->b, (swfdec_bits_left (&s->b) - swfdec_bits_left (&tmp)) / 8);
+    if (buffer == NULL)
+      break;
+    button->records = g_slist_prepend (button->records, buffer);
+    /* add hit state movies to button's extents */
+    if (flags & (1 << SWFDEC_BUTTON_HIT)) {
+      SwfdecGraphic *graphic = swfdec_swf_decoder_get_character (s, gid);
+      if (SWFDEC_IS_GRAPHIC (graphic)) {
+	SwfdecRect rect;
+	swfdec_rect_transform (&rect, &graphic->extents, &inverse);
+	swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents, &SWFDEC_GRAPHIC (button)->extents, &rect);
+      } else {
+	SWFDEC_ERROR ("graphic for id %u not found", gid);
+      }
+    }
+  }
+  
+  swfdec_bits_get_u8 (&s->b);
+  button->records = g_slist_reverse (button->records);
+
+  if (swfdec_bits_peek_u8 (&s->b)) {
+    char *script_name = g_strdup_printf ("Button%u", id);
+    button->events = swfdec_event_list_new (SWFDEC_DECODER (s)->player);
+    SWFDEC_LOG ("  event for button press");
+    swfdec_event_list_parse (button->events, &s->b, s->version, 1 << SWFDEC_EVENT_RELEASE, 
+	0, script_name);
+    g_free (script_name);
+  } else {
+    swfdec_bits_get_u8 (&s->b);
+  }
+  if (swfdec_bits_left (&s->b)) {
+    SWFDEC_WARNING ("%u bytes left after parsing script", swfdec_bits_left (&s->b) / 8);
+  }
 
   return SWFDEC_STATUS_OK;
 }
commit 9226d57caae7240e27e2c7e609d6e4aaf6de84ed
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 09:47:30 2007 +0100

    get rid of SwfdecContent
    
    Weeeeeee....
    I was so hoping to get rid of it.

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index d1c0296..33717b0 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -1604,34 +1604,6 @@ swfdec_movie_duplicate (SwfdecMovie *movie, const char *name, int depth)
   return copy;
 }
 
-SwfdecMovie *
-swfdec_movie_new_for_content (SwfdecMovie *parent, const SwfdecContent *content)
-{
-  SwfdecPlayer *player;
-  SwfdecMovie *movie;
-
-  g_return_val_if_fail (SWFDEC_IS_MOVIE (parent), NULL);
-  g_return_val_if_fail (SWFDEC_IS_GRAPHIC (content->graphic), NULL);
-  g_return_val_if_fail (swfdec_movie_find (parent, content->depth) == NULL, NULL);
-
-  SWFDEC_DEBUG ("new movie for parent %p", parent);
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (parent)->context);
-  movie = swfdec_movie_new (player, content->depth, parent, parent->resource, content->graphic, 
-      content->name ? swfdec_as_context_get_string (SWFDEC_AS_CONTEXT (player), content->name) : NULL);
-
-  swfdec_movie_set_static_properties (movie, content->has_transform ? &content->transform : NULL,
-      content->has_color_transform ? &content->color_transform : NULL, 
-      content->ratio, content->clip_depth, content->blend_mode, content->events);
-  if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
-    swfdec_movie_queue_script (movie, SWFDEC_EVENT_INITIALIZE);
-    swfdec_movie_queue_script (movie, SWFDEC_EVENT_CONSTRUCT);
-    swfdec_movie_queue_script (movie, SWFDEC_EVENT_LOAD);
-  }
-  swfdec_movie_initialize (movie);
-
-  return movie;
-}
-
 static void
 swfdec_movie_load_variables_on_finish (SwfdecAsObject *target,
     const char *text)
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 678a0da..4e43342 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -62,27 +62,6 @@ typedef enum {
 #define SWFDEC_BLEND_MODE_OVERLAY	13
 #define SWFDEC_BLEND_MODE_HARDLIGHT	14
 
-struct _SwfdecContent {
-  SwfdecGraphic *	graphic;	/* object to display */
-  int	         	depth;		/* at which depth to display */
-  int			clip_depth;	/* clip depth of object */
-  guint			ratio;
-  cairo_matrix_t	transform;
-  SwfdecColorTransform	color_transform;
-  gboolean		has_transform : 1;
-  gboolean		has_color_transform : 1;
-  char *		name;
-  SwfdecEventList *	events;
-  guint			blend_mode;	/* operator to use when painting (aka blend mode) */   
-
-  /* only used by buttons */
-  SwfdecContent *	sequence;
-  guint			start;
-  guint			end;
-};
-#define SWFDEC_CONTENT_DEFAULT { NULL, -1, 0, 0, { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, \
-  { 256, 0, 256, 0, 256, 0, 256, 0 }, NULL, NULL, CAIRO_OPERATOR_OVER, NULL, 0, G_MAXUINT, FALSE }
-
 #define SWFDEC_TYPE_MOVIE                    (swfdec_movie_get_type())
 #define SWFDEC_IS_MOVIE(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_MOVIE))
 #define SWFDEC_IS_MOVIE_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_MOVIE))
@@ -220,8 +199,6 @@ SwfdecMovie *	swfdec_movie_new		(SwfdecPlayer *		player,
 						 SwfdecResource *	resource,
 						 SwfdecGraphic *	graphic,
 						 const char *		name);
-SwfdecMovie *	swfdec_movie_new_for_content  	(SwfdecMovie *		parent,
-						 const SwfdecContent *	content);
 SwfdecMovie *	swfdec_movie_duplicate		(SwfdecMovie *		movie, 
 						 const char *		name,
 						 int			depth);
diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index e81c688..d17cbd5 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -36,15 +36,6 @@
 
 G_DEFINE_TYPE (SwfdecSprite, swfdec_sprite, SWFDEC_TYPE_GRAPHIC)
 
-void
-swfdec_content_free (SwfdecContent *content)
-{
-  g_free (content->name);
-  if (content->events)
-    swfdec_event_list_free (content->events);
-  g_free (content);
-}
-
 static void
 swfdec_sprite_dispose (GObject *object)
 {
@@ -155,17 +146,6 @@ tag_func_set_background_color (SwfdecSwfDecoder * s, guint tag)
   return SWFDEC_STATUS_OK;
 }
 
-SwfdecContent *
-swfdec_content_new (int depth)
-{
-  SwfdecContent *content = g_new0 (SwfdecContent, 1);
-
-  cairo_matrix_init_identity (&content->transform);
-  swfdec_color_transform_init_identity (&content->color_transform);
-  content->depth = depth;
-  return content;
-}
-
 static SwfdecMovie *
 swfdec_sprite_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
diff --git a/libswfdec/swfdec_sprite.h b/libswfdec/swfdec_sprite.h
index 34a9c49..6c9d4b9 100644
--- a/libswfdec/swfdec_sprite.h
+++ b/libswfdec/swfdec_sprite.h
@@ -93,9 +93,6 @@ gboolean	swfdec_sprite_get_action	(SwfdecSprite *		sprite,
 int		swfdec_sprite_get_frame		(SwfdecSprite *		sprite,
 				      		 const char *		label);
 
-SwfdecContent *swfdec_content_new (int depth);
-void swfdec_content_free (SwfdecContent *content);
-
 int tag_func_set_background_color (SwfdecSwfDecoder * s, guint tag);
 
 
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index 692a0a0..f08db53 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -37,7 +37,6 @@
 #include "swfdec_font.h"
 #include "swfdec_image.h"
 #include "swfdec_morphshape.h"
-#include "swfdec_movie.h" /* for SwfdecContent */
 #include "swfdec_pattern.h"
 #include "swfdec_player_internal.h"
 #include "swfdec_script_internal.h"
diff --git a/libswfdec/swfdec_types.h b/libswfdec/swfdec_types.h
index 2a9149a..d484396 100644
--- a/libswfdec/swfdec_types.h
+++ b/libswfdec/swfdec_types.h
@@ -36,7 +36,6 @@ typedef struct _SwfdecCache SwfdecCache;
 typedef struct _SwfdecCacheHandle SwfdecCacheHandle;
 typedef struct _SwfdecCharacter SwfdecCharacter;
 typedef struct _SwfdecColorTransform SwfdecColorTransform;
-typedef struct _SwfdecContent SwfdecContent;
 typedef struct _SwfdecDecoder SwfdecDecoder;
 typedef struct _SwfdecDraw SwfdecDraw;
 typedef struct _SwfdecEventList SwfdecEventList;
commit 865f797c8b3f4007c05f65bd529a4f4f3a428c84
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 09:37:32 2007 +0100

    add a big test for button events

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 1012d61..3ceae26 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -210,11 +210,15 @@ swfdec_button_movie_mouse_release (SwfdecMovie *movie, guint button)
   player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
   if (player->mouse_below == movie) {
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
+
+    SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
   } else {
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
-  }
 
-  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
+    /* NB: We don't chain to parent here for menubuttons*/
+    if (!SWFDEC_BUTTON_MOVIE (movie)->button->menubutton)
+      SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
+  }
 }
 
 static void
diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index a9f99a7..15d6af3 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -280,12 +280,10 @@ swfdec_sprite_movie_perform_place (SwfdecSpriteMovie *movie, SwfdecBits *bits, g
 	key_code = 0;
 
       SWFDEC_INFO ("clip event with flags 0x%X, key code %d", event_flags, key_code);
-#define SWFDEC_IMPLEMENTED_EVENTS \
-  ((1<< SWFDEC_EVENT_LOAD) | (1<<SWFDEC_EVENT_UNLOAD) | (1<<SWFDEC_EVENT_ENTER) | \
-   (1<< SWFDEC_EVENT_INITIALIZE) | (1<<SWFDEC_EVENT_CONSTRUCT) | \
-   (1<< SWFDEC_EVENT_MOUSE_DOWN) | (1<<SWFDEC_EVENT_MOUSE_MOVE) | (1<<SWFDEC_EVENT_MOUSE_UP))
-      if (event_flags & ~SWFDEC_IMPLEMENTED_EVENTS) {
-	SWFDEC_ERROR ("using non-implemented clip events %u", event_flags & ~SWFDEC_IMPLEMENTED_EVENTS);
+#define SWFDEC_UNIMPLEMENTED_EVENTS \
+  ((1<< SWFDEC_EVENT_DATA) | (1<<SWFDEC_EVENT_KEY_PRESS))
+      if (event_flags & SWFDEC_UNIMPLEMENTED_EVENTS) {
+	SWFDEC_ERROR ("using non-implemented clip events %u", event_flags & SWFDEC_UNIMPLEMENTED_EVENTS);
       }
       swfdec_event_list_parse (events, &action_bits, version, 
 	  event_flags, key_code, script_name);
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 6bc3116..6eef89d 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -290,6 +290,31 @@ EXTRA_DIST = \
 	boolean-properties-7.swf.trace \
 	boolean-properties-8.swf \
 	boolean-properties-8.swf.trace \
+	button-events-button-5.swf \
+	button-events-button-5.swf.act \
+	button-events-button-5.swf.trace \
+	button-events-button-6.swf \
+	button-events-button-6.swf.act \
+	button-events-button-6.swf.trace \
+	button-events-button-7.swf \
+	button-events-button-7.swf.act \
+	button-events-button-7.swf.trace \
+	button-events-button-8.swf \
+	button-events-button-8.swf.act \
+	button-events-button-8.swf.trace \
+	button-events.c \
+	button-events-menu-5.swf \
+	button-events-menu-5.swf.act \
+	button-events-menu-5.swf.trace \
+	button-events-menu-6.swf \
+	button-events-menu-6.swf.act \
+	button-events-menu-6.swf.trace \
+	button-events-menu-7.swf \
+	button-events-menu-7.swf.act \
+	button-events-menu-7.swf.trace \
+	button-events-menu-8.swf \
+	button-events-menu-8.swf.act \
+	button-events-menu-8.swf.trace \
 	button-properties.as \
 	button-properties-5.swf \
 	button-properties-5.swf.trace \
diff --git a/test/trace/button-events-button-5.swf b/test/trace/button-events-button-5.swf
new file mode 100644
index 0000000..c669574
Binary files /dev/null and b/test/trace/button-events-button-5.swf differ
diff --git a/test/trace/button-events-button-5.swf.act b/test/trace/button-events-button-5.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-button-5.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-button-5.swf.trace b/test/trace/button-events-button-5.swf.trace
new file mode 100644
index 0000000..65a55a8
--- /dev/null
+++ b/test/trace/button-events-button-5.swf.trace
@@ -0,0 +1,60 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance11.over4
+load _level0.button.instance12.over2
+load _level0.button.instance13.up_over
+button OverDown => OutDown: _level0
+unload _level0.button.instance11.over4
+unload _level0.button.instance12.over2
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.up_down
+button OutDown => OverDown: _level0
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance16.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance22.up_down
+load _level0.button.instance23.over4
+load _level0.button.instance24.over2
+load _level0.button.instance25.up_over
+button OverDown => OutDown: _level0
+unload _level0.button.instance23.over4
+unload _level0.button.instance24.over2
+unload _level0.button.instance7.over_down
+load _level0.button.instance26.up2
+load _level0.button.instance27.up3
+load _level0.button.instance28.up_down
+button OutDown => Idle: _level0
diff --git a/test/trace/button-events-button-6.swf b/test/trace/button-events-button-6.swf
new file mode 100644
index 0000000..820fb33
Binary files /dev/null and b/test/trace/button-events-button-6.swf differ
diff --git a/test/trace/button-events-button-6.swf.act b/test/trace/button-events-button-6.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-button-6.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-button-6.swf.trace b/test/trace/button-events-button-6.swf.trace
new file mode 100644
index 0000000..752c2fc
--- /dev/null
+++ b/test/trace/button-events-button-6.swf.trace
@@ -0,0 +1,68 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+onRollOver: _level0.button
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance11.over4
+load _level0.button.instance12.over2
+load _level0.button.instance13.up_over
+button OverDown => OutDown: _level0
+onDragOut: _level0.button
+unload _level0.button.instance11.over4
+unload _level0.button.instance12.over2
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.up_down
+button OutDown => OverDown: _level0
+onDragOver: _level0.button
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance16.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+onRelease: _level0.button
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance22.up_down
+load _level0.button.instance23.over4
+load _level0.button.instance24.over2
+load _level0.button.instance25.up_over
+button OverDown => OutDown: _level0
+onDragOut: _level0.button
+unload _level0.button.instance23.over4
+unload _level0.button.instance24.over2
+unload _level0.button.instance7.over_down
+load _level0.button.instance26.up2
+load _level0.button.instance27.up3
+load _level0.button.instance28.up_down
+button OutDown => Idle: _level0
+onReleaseOutside: _level0.button
diff --git a/test/trace/button-events-button-7.swf b/test/trace/button-events-button-7.swf
new file mode 100644
index 0000000..2dadd1d
Binary files /dev/null and b/test/trace/button-events-button-7.swf differ
diff --git a/test/trace/button-events-button-7.swf.act b/test/trace/button-events-button-7.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-button-7.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-button-7.swf.trace b/test/trace/button-events-button-7.swf.trace
new file mode 100644
index 0000000..752c2fc
--- /dev/null
+++ b/test/trace/button-events-button-7.swf.trace
@@ -0,0 +1,68 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+onRollOver: _level0.button
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance11.over4
+load _level0.button.instance12.over2
+load _level0.button.instance13.up_over
+button OverDown => OutDown: _level0
+onDragOut: _level0.button
+unload _level0.button.instance11.over4
+unload _level0.button.instance12.over2
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.up_down
+button OutDown => OverDown: _level0
+onDragOver: _level0.button
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance16.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+onRelease: _level0.button
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance22.up_down
+load _level0.button.instance23.over4
+load _level0.button.instance24.over2
+load _level0.button.instance25.up_over
+button OverDown => OutDown: _level0
+onDragOut: _level0.button
+unload _level0.button.instance23.over4
+unload _level0.button.instance24.over2
+unload _level0.button.instance7.over_down
+load _level0.button.instance26.up2
+load _level0.button.instance27.up3
+load _level0.button.instance28.up_down
+button OutDown => Idle: _level0
+onReleaseOutside: _level0.button
diff --git a/test/trace/button-events-button-8.swf b/test/trace/button-events-button-8.swf
new file mode 100644
index 0000000..cbc15ee
Binary files /dev/null and b/test/trace/button-events-button-8.swf differ
diff --git a/test/trace/button-events-button-8.swf.act b/test/trace/button-events-button-8.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-button-8.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-button-8.swf.trace b/test/trace/button-events-button-8.swf.trace
new file mode 100644
index 0000000..752c2fc
--- /dev/null
+++ b/test/trace/button-events-button-8.swf.trace
@@ -0,0 +1,68 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+onRollOver: _level0.button
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance11.over4
+load _level0.button.instance12.over2
+load _level0.button.instance13.up_over
+button OverDown => OutDown: _level0
+onDragOut: _level0.button
+unload _level0.button.instance11.over4
+unload _level0.button.instance12.over2
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.up_down
+button OutDown => OverDown: _level0
+onDragOver: _level0.button
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance16.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+onRelease: _level0.button
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance22.up_down
+load _level0.button.instance23.over4
+load _level0.button.instance24.over2
+load _level0.button.instance25.up_over
+button OverDown => OutDown: _level0
+onDragOut: _level0.button
+unload _level0.button.instance23.over4
+unload _level0.button.instance24.over2
+unload _level0.button.instance7.over_down
+load _level0.button.instance26.up2
+load _level0.button.instance27.up3
+load _level0.button.instance28.up_down
+button OutDown => Idle: _level0
+onReleaseOutside: _level0.button
diff --git a/test/trace/button-events-menu-5.swf b/test/trace/button-events-menu-5.swf
new file mode 100644
index 0000000..2892fda
Binary files /dev/null and b/test/trace/button-events-menu-5.swf differ
diff --git a/test/trace/button-events-menu-5.swf.act b/test/trace/button-events-menu-5.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-menu-5.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-menu-5.swf.trace b/test/trace/button-events-menu-5.swf.trace
new file mode 100644
index 0000000..10f1ff0
--- /dev/null
+++ b/test/trace/button-events-menu-5.swf.trace
@@ -0,0 +1,53 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance7.over_down
+load _level0.button.instance11.up2
+load _level0.button.instance12.up3
+load _level0.button.instance13.up_over
+button OverDown => Idle: _level0
+unload _level0.button.instance11.up2
+unload _level0.button.instance12.up3
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.over_down
+button Idle => OutDown: _level0
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance16.over_down
+load _level0.button.instance23.up2
+load _level0.button.instance24.up3
+load _level0.button.instance25.up_over
+button OverDown => Idle: _level0
diff --git a/test/trace/button-events-menu-6.swf b/test/trace/button-events-menu-6.swf
new file mode 100644
index 0000000..f535879
Binary files /dev/null and b/test/trace/button-events-menu-6.swf differ
diff --git a/test/trace/button-events-menu-6.swf.act b/test/trace/button-events-menu-6.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-menu-6.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-menu-6.swf.trace b/test/trace/button-events-menu-6.swf.trace
new file mode 100644
index 0000000..6f9f001
--- /dev/null
+++ b/test/trace/button-events-menu-6.swf.trace
@@ -0,0 +1,60 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+onRollOver: _level0.button
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance7.over_down
+load _level0.button.instance11.up2
+load _level0.button.instance12.up3
+load _level0.button.instance13.up_over
+button OverDown => Idle: _level0
+onDragOut: _level0.button
+unload _level0.button.instance11.up2
+unload _level0.button.instance12.up3
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.over_down
+button Idle => OutDown: _level0
+onDragOver: _level0.button
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+onRelease: _level0.button
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance16.over_down
+load _level0.button.instance23.up2
+load _level0.button.instance24.up3
+load _level0.button.instance25.up_over
+button OverDown => Idle: _level0
+onDragOut: _level0.button
diff --git a/test/trace/button-events-menu-7.swf b/test/trace/button-events-menu-7.swf
new file mode 100644
index 0000000..04c3b27
Binary files /dev/null and b/test/trace/button-events-menu-7.swf differ
diff --git a/test/trace/button-events-menu-7.swf.act b/test/trace/button-events-menu-7.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-menu-7.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-menu-7.swf.trace b/test/trace/button-events-menu-7.swf.trace
new file mode 100644
index 0000000..6f9f001
--- /dev/null
+++ b/test/trace/button-events-menu-7.swf.trace
@@ -0,0 +1,60 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+onRollOver: _level0.button
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance7.over_down
+load _level0.button.instance11.up2
+load _level0.button.instance12.up3
+load _level0.button.instance13.up_over
+button OverDown => Idle: _level0
+onDragOut: _level0.button
+unload _level0.button.instance11.up2
+unload _level0.button.instance12.up3
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.over_down
+button Idle => OutDown: _level0
+onDragOver: _level0.button
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+onRelease: _level0.button
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance16.over_down
+load _level0.button.instance23.up2
+load _level0.button.instance24.up3
+load _level0.button.instance25.up_over
+button OverDown => Idle: _level0
+onDragOut: _level0.button
diff --git a/test/trace/button-events-menu-8.swf b/test/trace/button-events-menu-8.swf
new file mode 100644
index 0000000..b13d0d0
Binary files /dev/null and b/test/trace/button-events-menu-8.swf differ
diff --git a/test/trace/button-events-menu-8.swf.act b/test/trace/button-events-menu-8.swf.act
new file mode 100644
index 0000000..352902b
--- /dev/null
+++ b/test/trace/button-events-menu-8.swf.act
@@ -0,0 +1,17 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+move 50, 50
+wait 1000
+up
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/button-events-menu-8.swf.trace b/test/trace/button-events-menu-8.swf.trace
new file mode 100644
index 0000000..6f9f001
--- /dev/null
+++ b/test/trace/button-events-menu-8.swf.trace
@@ -0,0 +1,60 @@
+load _level0.button.instance1.up2
+load _level0.button.instance2.up3
+load _level0.button.instance3.up_down
+load _level0.button.instance4.up_over
+unload _level0.button.instance1.up2
+unload _level0.button.instance2.up3
+unload _level0.button.instance3.up_down
+load _level0.button.instance5.over4
+load _level0.button.instance6.over2
+load _level0.button.instance7.over_down
+button Idle => OverUp: _level0
+onRollOver: _level0.button
+unload _level0.button.instance5.over4
+unload _level0.button.instance6.over2
+unload _level0.button.instance4.up_over
+load _level0.button.instance8.down2
+load _level0.button.instance9.down5
+load _level0.button.instance10.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance8.down2
+unload _level0.button.instance9.down5
+unload _level0.button.instance7.over_down
+load _level0.button.instance11.up2
+load _level0.button.instance12.up3
+load _level0.button.instance13.up_over
+button OverDown => Idle: _level0
+onDragOut: _level0.button
+unload _level0.button.instance11.up2
+unload _level0.button.instance12.up3
+unload _level0.button.instance13.up_over
+load _level0.button.instance14.down2
+load _level0.button.instance15.down5
+load _level0.button.instance16.over_down
+button Idle => OutDown: _level0
+onDragOver: _level0.button
+unload _level0.button.instance14.down2
+unload _level0.button.instance15.down5
+unload _level0.button.instance10.up_down
+load _level0.button.instance17.over4
+load _level0.button.instance18.over2
+load _level0.button.instance19.up_over
+button OverDown => OverUp: _level0
+onRelease: _level0.button
+unload _level0.button.instance17.over4
+unload _level0.button.instance18.over2
+unload _level0.button.instance19.up_over
+load _level0.button.instance20.down2
+load _level0.button.instance21.down5
+load _level0.button.instance22.up_down
+button OverUp => OverDown: _level0
+onPress: _level0.button
+unload _level0.button.instance20.down2
+unload _level0.button.instance21.down5
+unload _level0.button.instance16.over_down
+load _level0.button.instance23.up2
+load _level0.button.instance24.up3
+load _level0.button.instance25.up_over
+button OverDown => Idle: _level0
+onDragOut: _level0.button
diff --git a/test/trace/button-events.c b/test/trace/button-events.c
new file mode 100644
index 0000000..dad2eb0
--- /dev/null
+++ b/test/trace/button-events.c
@@ -0,0 +1,144 @@
+/* gcc `pkg-config --libs --cflags libming` button-events.c -o button-events && ./button-events
+ */
+
+#include <ming.h>
+
+static const char *events[] = { "Press", "Release", "ReleaseOutside", "RollOver", "RollOut", "DragOver", "DragOut" };
+static const char *button_events[] = { "Idle => OverUp", "OverUp => Idle", "OverUp => OverDown", "OverDown => OverUp", "OverDown => OutDown", "OutDown => OverDown", "OutDown => Idle", "Idle => OutDown", "OverDown => Idle" };
+
+static void
+add_button_events (SWFButton button)
+{
+  char script[100];
+  unsigned int i;
+
+  for (i = 0; i < sizeof (button_events) / sizeof (button_events[0]); i++) {
+    sprintf (script, "trace (\"button %s: \" + this);", button_events[i]);
+    SWFButton_addAction (button, newSWFAction (script), (1 << i));
+  }
+}
+
+static SWFCharacter
+get_clip_events_movie (const char *name)
+{
+  SWFMovieClip clip;
+  SWFDisplayItem item;
+
+  clip = newSWFMovieClip ();
+  item = SWFMovieClip_add (clip, (SWFBlock) newSWFMovieClip ());
+  SWFDisplayItem_addAction (item, newSWFAction ("trace (\"load \" + this);"), SWFACTION_ONLOAD);
+  SWFDisplayItem_addAction (item, newSWFAction ("trace (\"unload \" + this);"), SWFACTION_UNLOAD);
+  SWFDisplayItem_setName (item, name);
+  SWFMovieClip_nextFrame (clip);
+  return (SWFCharacter) clip;
+}
+
+static void
+add_item_events (SWFDisplayItem item)
+{
+  char script[100];
+  unsigned int i;
+
+  for (i = 0; i < sizeof (events) / sizeof (events[0]); i++) {
+    sprintf (script, "trace (\"place %s: \" + this);", events[i]);
+    SWFDisplayItem_addAction (item, newSWFAction (script), 1 << (10 + i));
+  }
+}
+
+static SWFCharacter
+get_rectangle (int r, int g, int b)
+{
+  SWFShape shape;
+  SWFFillStyle fill;
+
+  shape = newSWFShape ();
+  fill = SWFShape_addSolidFillStyle (shape, r, g, b, 255);
+  SWFShape_setRightFillStyle (shape, fill);
+  SWFShape_drawLineTo (shape, 100, 0);
+  SWFShape_drawLineTo (shape, 100, 100);
+  SWFShape_drawLineTo (shape, 0, 100);
+  SWFShape_drawLineTo (shape, 0, 0);
+
+  return (SWFCharacter) shape;
+}
+
+static void
+do_movie (int version, int menu)
+{
+  char name[100];
+  SWFMovie movie;
+  SWFDisplayItem item;
+  SWFButton button;
+  SWFButtonRecord rec;
+
+  movie = newSWFMovieWithVersion (version);
+  SWFMovie_setRate (movie, 10);
+  SWFMovie_setDimension (movie, 200, 150);
+
+  SWFMovie_add (movie, newSWFInitAction (newSWFAction (
+	  "button.onPress = function () { trace (\"onPress: \" + this); };"
+	  "button.onRelease = function () { trace (\"onRelease: \" + this); };"
+	  "button.onReleaseOutside = function () { trace (\"onReleaseOutside: \" + this); };"
+	  "button.onRollOver = function () { trace (\"onRollOver: \" + this); };"
+	  "button.onRollOut = function () { trace (\"onRollOut: \" + this); };"
+	  "button.onDragOver = function () { trace (\"onDragOver: \" + this); };"
+	  "button.onDragOut = function () { trace (\"onDragOut: \" + this); };"
+	  )));
+  button = newSWFButton ();
+  SWFButton_setMenu (button, menu);
+  rec = SWFButton_addCharacter (button, get_rectangle (255, 0, 0), SWFBUTTON_UP | SWFBUTTON_HIT);
+  SWFButtonRecord_setDepth (rec, 1);
+  rec = SWFButton_addCharacter (button, get_rectangle (0, 255, 0), SWFBUTTON_OVER);
+  SWFButtonRecord_setDepth (rec, 1);
+  rec = SWFButton_addCharacter (button, get_rectangle (0, 0, 255), SWFBUTTON_DOWN);
+  SWFButtonRecord_setDepth (rec, 1);
+
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("up2"), SWFBUTTON_UP);
+  SWFButtonRecord_setDepth (rec, 2);
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("up3"), SWFBUTTON_UP);
+  SWFButtonRecord_setDepth (rec, 3);
+
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("over4"), SWFBUTTON_OVER);
+  SWFButtonRecord_setDepth (rec, 4);
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("over2"), SWFBUTTON_OVER);
+  SWFButtonRecord_setDepth (rec, 2);
+
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("down2"), SWFBUTTON_DOWN);
+  SWFButtonRecord_setDepth (rec, 2);
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("down5"), SWFBUTTON_DOWN);
+  SWFButtonRecord_setDepth (rec, 5);
+
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("up_down"), SWFBUTTON_UP | SWFBUTTON_DOWN);
+  SWFButtonRecord_setDepth (rec, 6);
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("up_over"), SWFBUTTON_UP | SWFBUTTON_OVER);
+  SWFButtonRecord_setDepth (rec, 7);
+  rec = SWFButton_addCharacter (button, get_clip_events_movie ("over_down"), SWFBUTTON_DOWN | SWFBUTTON_OVER);
+  SWFButtonRecord_setDepth (rec, 8);
+
+  add_button_events (button);
+  item = SWFMovie_add (movie, button);
+  add_item_events (item);
+  SWFDisplayItem_setDepth (item, 0);
+  SWFDisplayItem_setName (item, "button");
+
+  SWFMovie_nextFrame (movie);
+
+  sprintf (name, "button-events-%s-%d.swf", menu ? "menu" : "button", version);
+  SWFMovie_save (movie, name);
+}
+
+int
+main (int argc, char **argv)
+{
+  int i;
+
+  if (Ming_init ())
+    return 1;
+
+  for (i = 8; i >= 5; i--) {
+    do_movie (i, 0);
+    do_movie (i, 1);
+  }
+
+  return 0;
+}
commit da5e4ef29fc7f2991595e6e3695b616a78382598
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 09:25:10 2007 +0100

    seems there's no special event for buttons that are released outside

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 80bf4b6..1012d61 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -215,10 +215,6 @@ swfdec_button_movie_mouse_release (SwfdecMovie *movie, guint button)
   }
 
   SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
-
-  if (player->mouse_below == movie) {
-    swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OVER);
-  }
 }
 
 static void
commit 8894d274f807156a5f99b01f48e8a7138554e4a8
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 28 09:23:06 2007 +0100

    translate conditions differently for menu buttons and normal ones

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 7cd3f27..3cbfb7a 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -87,26 +87,25 @@ swfdec_button_class_init (SwfdecButtonClass * g_class)
 }
 
 static guint
-swfdec_button_translate_conditions (guint conditions)
+swfdec_button_translate_conditions (guint conditions, gboolean menu)
 {
-  /* FIXME: This assumes IDLE<=>OVER_DOWN is the same as DRAG_OVER/OUT, is that correct? */
-  static const SwfdecEventType events[] = { 
-    /* idle => over up */	SWFDEC_EVENT_ROLL_OVER, 
-    /* over up => idle */	SWFDEC_EVENT_ROLL_OUT,
-    /* over up => over down */	SWFDEC_EVENT_PRESS,
-    /* over down => over up */	SWFDEC_EVENT_RELEASE,
-    /* over down => out down */	SWFDEC_EVENT_DRAG_OUT,
-    /* out down => over down */	SWFDEC_EVENT_DRAG_OVER,
-    /* out down => idle */	SWFDEC_EVENT_RELEASE_OUTSIDE,
-    /* idle => over down */	SWFDEC_EVENT_DRAG_OVER,
-    /* over down => idle */	SWFDEC_EVENT_DRAG_OUT 
+  static const guint events[][2] = { 
+    /* idle => over up */	{ 1 << SWFDEC_EVENT_ROLL_OVER, 1 << SWFDEC_EVENT_ROLL_OVER },
+    /* over up => idle */	{ 1 << SWFDEC_EVENT_ROLL_OUT, 1 << SWFDEC_EVENT_ROLL_OUT },
+    /* over up => over down */	{ 1 << SWFDEC_EVENT_PRESS, 1 << SWFDEC_EVENT_PRESS },
+    /* over down => over up */	{ 1 << SWFDEC_EVENT_RELEASE, 1 << SWFDEC_EVENT_RELEASE },
+    /* over down => out down */	{ 1 << SWFDEC_EVENT_DRAG_OUT, 0 },
+    /* out down => over down */	{ 1 << SWFDEC_EVENT_DRAG_OVER, 0 },
+    /* out down => idle */	{ 1 << SWFDEC_EVENT_RELEASE_OUTSIDE, 1 << SWFDEC_EVENT_RELEASE_OUTSIDE },
+    /* idle => over down */	{ 0, 1 << SWFDEC_EVENT_DRAG_OVER },
+    /* over down => idle */	{ 0, 1 << SWFDEC_EVENT_DRAG_OUT }
   };
   guint i, ret;
 
   ret = 0;
   for (i = 0; i <= G_N_ELEMENTS (events); i++) {
     if (conditions & (1 << i))
-      ret |= (1 << events[i]);
+      ret |= events[i][menu ? 1 : 0];
   }
   return ret;
 }
@@ -209,7 +208,7 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
     condition = swfdec_bits_get_u16 (&bits);
     key = condition >> 9;
     condition &= 0x1FF;
-    condition = swfdec_button_translate_conditions (condition);
+    condition = swfdec_button_translate_conditions (condition, button->menubutton);
 
     SWFDEC_LOG (" length = %d", length);
 
commit d3ae6fa2cde4e54fd5ccadab3a07fed300f9cd73
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 21:46:34 2007 +0100

    make the event translation better readable

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index b9de3d0..7cd3f27 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -90,13 +90,21 @@ static guint
 swfdec_button_translate_conditions (guint conditions)
 {
   /* FIXME: This assumes IDLE<=>OVER_DOWN is the same as DRAG_OVER/OUT, is that correct? */
-  static const SwfdecEventType events[] = { SWFDEC_EVENT_ROLL_OVER, SWFDEC_EVENT_ROLL_OUT,
-    SWFDEC_EVENT_PRESS, SWFDEC_EVENT_RELEASE, SWFDEC_EVENT_DRAG_OUT, SWFDEC_EVENT_DRAG_OVER,
-    SWFDEC_EVENT_RELEASE_OUTSIDE, SWFDEC_EVENT_DRAG_OVER, SWFDEC_EVENT_DRAG_OUT };
+  static const SwfdecEventType events[] = { 
+    /* idle => over up */	SWFDEC_EVENT_ROLL_OVER, 
+    /* over up => idle */	SWFDEC_EVENT_ROLL_OUT,
+    /* over up => over down */	SWFDEC_EVENT_PRESS,
+    /* over down => over up */	SWFDEC_EVENT_RELEASE,
+    /* over down => out down */	SWFDEC_EVENT_DRAG_OUT,
+    /* out down => over down */	SWFDEC_EVENT_DRAG_OVER,
+    /* out down => idle */	SWFDEC_EVENT_RELEASE_OUTSIDE,
+    /* idle => over down */	SWFDEC_EVENT_DRAG_OVER,
+    /* over down => idle */	SWFDEC_EVENT_DRAG_OUT 
+  };
   guint i, ret;
 
   ret = 0;
-  for (i = 0; i <= 8; i++) {
+  for (i = 0; i <= G_N_ELEMENTS (events); i++) {
     if (conditions & (1 << i))
       ret |= (1 << events[i]);
   }
commit 6161c7e3ae176e4001b1fecc76fc63a289d8ec55
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 21:46:19 2007 +0100

    onFoo events are emitted on the button

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 4a0874f..d1c0296 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -448,7 +448,7 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
     return;
   name = swfdec_event_type_get_name (condition);
   if (name != NULL) {
-    swfdec_as_object_call_with_security (thisp,
+    swfdec_as_object_call_with_security (SWFDEC_AS_OBJECT (movie),
 	SWFDEC_SECURITY (movie->resource), name, 0, NULL, NULL);
   }
   if (condition == SWFDEC_EVENT_CONSTRUCT)
commit 8c3c96c57a982eec89153858c078d44188454ca9
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 19:14:15 2007 +0100

    remove debugging g_print()

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index c78e414..80bf4b6 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -122,7 +122,6 @@ swfdec_button_movie_set_state (SwfdecButtonMovie *button, SwfdecButtonState stat
     return;
   }
   SWFDEC_DEBUG ("changing state from %d to %d", button->state, state);
-  g_print ("changing state from %d to %d\n", button->state, state);
   /* remove all movies that aren't in the new state */
   new = 1 << state;
   if (button->state >= 0) {
commit 08aabd4c39ffc4285e243ccb789ceb5ae31bd683
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 19:13:49 2007 +0100

    remove button dumping code
    
    IT doesn't work anymore

diff --git a/test/dump.c b/test/dump.c
index 38a456d..77bd382 100644
--- a/test/dump.c
+++ b/test/dump.c
@@ -282,23 +282,6 @@ dump_font (SwfdecFont *font)
 static void
 dump_button (SwfdecButton *button)
 {
-  GList *walk;
-
-#define SWFDEC_CONTENT_IN_STATE(content, state) \
-  ((content)->sequence->start <= state && \
-   (content)->sequence->end > state)
-  if (verbose) {
-    for (walk = button->records; walk; walk = walk->next) {
-      SwfdecContent *content = walk->data;
-
-      g_print ("  %s %s %s %s  %s %d\n", 
-	  SWFDEC_CONTENT_IN_STATE (content, SWFDEC_BUTTON_UP) ? "U" : " ",
-	  SWFDEC_CONTENT_IN_STATE (content, SWFDEC_BUTTON_OVER) ? "O" : " ",
-	  SWFDEC_CONTENT_IN_STATE (content, SWFDEC_BUTTON_DOWN) ? "D" : " ",
-	  SWFDEC_CONTENT_IN_STATE (content, SWFDEC_BUTTON_HIT) ? "H" : " ",
-	  G_OBJECT_TYPE_NAME (content->graphic), SWFDEC_CHARACTER (content->graphic)->id);
-    }
-  }
 }
 
 static const char *
commit 2b6c8aa3467007cf5883dcb2c06f1541b9280919
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 19:07:27 2007 +0100

    button events are executed _after_ load/unload events of children

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 5e1583f..c78e414 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -165,18 +165,19 @@ swfdec_button_movie_mouse_events (SwfdecMovie *movie)
 static void
 swfdec_button_movie_mouse_in (SwfdecMovie *movie)
 {
-  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_in (movie);
   if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)))
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_DOWN);
   else
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
+
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_in (movie);
 }
 
 static void
 swfdec_button_movie_mouse_out (SwfdecMovie *movie)
 {
   SwfdecButtonMovie *button = SWFDEC_BUTTON_MOVIE (movie);
-  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_out (movie);
+
   if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context))) {
     if (button->button->menubutton) {
       swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
@@ -186,6 +187,8 @@ swfdec_button_movie_mouse_out (SwfdecMovie *movie)
   } else {
     swfdec_button_movie_set_state (button, SWFDEC_BUTTON_UP);
   }
+
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_out (movie);
 }
 
 static void
@@ -193,8 +196,9 @@ swfdec_button_movie_mouse_press (SwfdecMovie *movie, guint button)
 {
   if (button != 0)
     return;
-  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_press (movie, button);
   swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_DOWN);
+
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_press (movie, button);
 }
 
 static void
@@ -204,14 +208,18 @@ swfdec_button_movie_mouse_release (SwfdecMovie *movie, guint button)
 
   if (button != 0)
     return;
-  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
   player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
   if (player->mouse_below == movie) {
-    swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OVER);
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
   } else {
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
   }
+
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
+
+  if (player->mouse_below == movie) {
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OVER);
+  }
 }
 
 static void
commit ac6846661743d6005755ab74f05b6c0deb03fcee
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 19:06:33 2007 +0100

    button events get the parent movie as the this pointer

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 74d9b33..4a0874f 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -414,15 +414,22 @@ swfdec_movie_get_version (SwfdecMovie *movie)
 void
 swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
 {
+  SwfdecAsObject *thisp;
   const char *name;
 
   g_return_if_fail (SWFDEC_IS_MOVIE (movie));
 
-  /* special cases */
-  if (SWFDEC_IS_BUTTON_MOVIE (movie) && (
-	condition == SWFDEC_EVENT_CONSTRUCT || condition < SWFDEC_EVENT_PRESS))
-    return;
+  if (SWFDEC_IS_BUTTON_MOVIE (movie)) {
+    /* these conditions don't exist for buttons */
+    if (condition == SWFDEC_EVENT_CONSTRUCT || condition < SWFDEC_EVENT_PRESS)
+      return;
+    thisp = SWFDEC_AS_OBJECT (movie->parent);
+    g_assert (thisp);
+  } else {
+    thisp = SWFDEC_AS_OBJECT (movie);
+  }
 
+  /* special cases */
   if (condition == SWFDEC_EVENT_CONSTRUCT) {
     if (swfdec_movie_get_version (movie) <= 5)
       return;
@@ -433,7 +440,7 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
   }
 
   if (movie->events) {
-    swfdec_event_list_execute (movie->events, SWFDEC_AS_OBJECT (movie), 
+    swfdec_event_list_execute (movie->events, thisp,
 	SWFDEC_SECURITY (movie->resource), condition, 0);
   }
   /* FIXME: how do we compute the version correctly here? */
@@ -441,11 +448,11 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
     return;
   name = swfdec_event_type_get_name (condition);
   if (name != NULL) {
-    swfdec_as_object_call_with_security (SWFDEC_AS_OBJECT (movie), 
+    swfdec_as_object_call_with_security (thisp,
 	SWFDEC_SECURITY (movie->resource), name, 0, NULL, NULL);
   }
   if (condition == SWFDEC_EVENT_CONSTRUCT)
-    swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR_constructor, 0, NULL, NULL);
+    swfdec_as_object_call (thisp, SWFDEC_AS_STR_constructor, 0, NULL, NULL);
 }
 
 /**
commit bbdeba083af27bdb3faa6af6c2748fa5d412f374
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 19:02:04 2007 +0100

    use the condition as a flag, ot as an absolute value

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 700f8f8..b9de3d0 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -98,7 +98,7 @@ swfdec_button_translate_conditions (guint conditions)
   ret = 0;
   for (i = 0; i <= 8; i++) {
     if (conditions & (1 << i))
-      ret |= events[i];
+      ret |= (1 << events[i]);
   }
   return ret;
 }
commit c82496b87d3de0b358ed99ffeeb8f567d5807f61
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 13:56:48 2007 +0100

    keep a reference to the button from the button movie

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index ca2a1f3..700f8f8 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -67,9 +67,10 @@ swfdec_button_create_movie (SwfdecGraphic *graphic, gsize *size)
   SwfdecButton *button = SWFDEC_BUTTON (graphic);
   SwfdecButtonMovie *movie = g_object_new (SWFDEC_TYPE_BUTTON_MOVIE, NULL);
 
-  movie->button = button;
+  movie->button = g_object_ref (button);
   *size = sizeof (SwfdecButtonMovie);
-  SWFDEC_MOVIE (movie)->events = swfdec_event_list_copy (button->events);
+  if (button->events)
+    SWFDEC_MOVIE (movie)->events = swfdec_event_list_copy (button->events);
 
   return SWFDEC_MOVIE (movie);
 }
diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index f612b3d..5e1583f 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -264,10 +264,24 @@ swfdec_button_movie_mouse_change (SwfdecMovie *mov, double x, double y,
 #endif
 
 static void
+swfdec_button_movie_dispose (GObject *object)
+{
+  SwfdecButtonMovie *button = SWFDEC_BUTTON_MOVIE (object);
+
+  if (button->button) {
+    g_object_unref (button->button);
+    button->button = NULL;
+  }
+  G_OBJECT_CLASS (swfdec_button_movie_parent_class)->dispose (object);
+}
+
+static void
 swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
   SwfdecMovieClass *movie_class = SWFDEC_MOVIE_CLASS (g_class);
 
+  object_class->dispose = swfdec_button_movie_dispose;
   movie_class->init_movie = swfdec_button_movie_init_movie;
   movie_class->update_extents = swfdec_button_movie_update_extents;
 
commit 22f19754b3ed239c49779e0fe0adb7c32f3b0052
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 27 13:50:01 2007 +0100

    fix merge conflict

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 8c86e58..74d9b33 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -279,7 +279,7 @@ swfdec_movie_do_remove (SwfdecMovie *movie, gboolean destroy)
 
   if ((movie->events && 
 	swfdec_event_list_has_conditions (movie->events, SWFDEC_AS_OBJECT (movie), SWFDEC_EVENT_UNLOAD, 0)) ||
-      swfdec_as_object_has_function (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR_onUnload)) {
+      swfdec_as_object_has_variable (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR_onUnload)) {
     swfdec_movie_queue_script (movie, SWFDEC_EVENT_UNLOAD);
     destroy = FALSE;
   }
commit 6866ab4f66b2dce919ce16e372dd652f169c6ad2
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:33:20 2007 +0100

    remove commented out old code

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index a734d3b..f612b3d 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -40,171 +40,6 @@ swfdec_button_movie_update_extents (SwfdecMovie *movie,
       &SWFDEC_GRAPHIC (SWFDEC_BUTTON_MOVIE (movie)->button)->extents);
 }
 
-#if 0
-/* first index is 1 for menubutton, second index is previous state,
- * last index is current state
- * MSB in index is mouse OUT = 0, IN = 1
- * LSB in index is button UP = 0, DOWN = 1
- */
-static const SwfdecButtonCondition event_table[2][4][4] = {
-  { { -1, -1, SWFDEC_BUTTON_IDLE_TO_OVER_UP, -1 },
-    { SWFDEC_BUTTON_OUT_DOWN_TO_IDLE, -1, -1, SWFDEC_BUTTON_OUT_DOWN_TO_OVER_DOWN },
-    { SWFDEC_BUTTON_OVER_UP_TO_IDLE, -1, -1, SWFDEC_BUTTON_OVER_UP_TO_OVER_DOWN },
-    { -1, SWFDEC_BUTTON_OVER_DOWN_TO_OUT_DOWN, SWFDEC_BUTTON_OVER_DOWN_TO_OVER_UP, -1 } },
-  { { -1, -1, SWFDEC_BUTTON_IDLE_TO_OVER_UP, -1 },
-    { -2, -1, -1, SWFDEC_BUTTON_IDLE_TO_OVER_DOWN },
-    { SWFDEC_BUTTON_OVER_UP_TO_IDLE, -1, -1, SWFDEC_BUTTON_OVER_UP_TO_OVER_DOWN },
-    { -1, SWFDEC_BUTTON_OVER_DOWN_TO_IDLE, SWFDEC_BUTTON_OVER_DOWN_TO_OVER_UP, -1 } }
-};
-static const int sound_table[2][4][4] = {
-  { { -1, -1,  1, -1 },
-    {  0, -1, -1, -1 },
-    {  0, -1, -1,  2 },
-    { -1, -1,  3, -1 } },
-  { { -1, -1,  1, -1 },
-    { -1, -1, -1,  1 },
-    {  0, -1, -1,  2 },
-    { -1,  0,  3, -1 } }
-};
-
-static const char *
-swfdec_button_condition_get_name (SwfdecButtonCondition condition)
-{
-  /* FIXME: check if these events are based on conditions or if they're independant of button type */
-  switch (condition) {
-    case SWFDEC_BUTTON_IDLE_TO_OVER_UP:
-      return SWFDEC_AS_STR_onRollOver;
-    case SWFDEC_BUTTON_OVER_UP_TO_IDLE:
-      return SWFDEC_AS_STR_onRollOut;
-    case SWFDEC_BUTTON_OVER_UP_TO_OVER_DOWN:
-      return SWFDEC_AS_STR_onPress;
-    case SWFDEC_BUTTON_OVER_DOWN_TO_OVER_UP:
-      return SWFDEC_AS_STR_onRelease;
-    case SWFDEC_BUTTON_OVER_DOWN_TO_OUT_DOWN:
-      return SWFDEC_AS_STR_onDragOut;
-    case SWFDEC_BUTTON_OUT_DOWN_TO_OVER_DOWN:
-      return SWFDEC_AS_STR_onDragOver;
-    case SWFDEC_BUTTON_OUT_DOWN_TO_IDLE:
-      return SWFDEC_AS_STR_onReleaseOutside;
-    case SWFDEC_BUTTON_IDLE_TO_OVER_DOWN:
-      return SWFDEC_AS_STR_onDragOver;
-    case SWFDEC_BUTTON_OVER_DOWN_TO_IDLE:
-      return SWFDEC_AS_STR_onDragOut;
-    default:
-      g_assert_not_reached ();
-      return NULL;
-  }
-}
-
-static void
-swfdec_button_movie_execute (SwfdecButtonMovie *movie,
-    SwfdecButtonCondition condition)
-{
-  const char *name;
-
-  if (movie->button->menubutton) {
-    g_assert ((condition & ((1 << SWFDEC_BUTTON_OVER_DOWN_TO_OUT_DOWN) \
-                         | (1 << SWFDEC_BUTTON_OUT_DOWN_TO_OVER_DOWN) \
-                         | (1 << SWFDEC_BUTTON_OUT_DOWN_TO_IDLE))) == 0);
-  } else {
-    g_assert ((condition & ((1 << SWFDEC_BUTTON_IDLE_TO_OVER_DOWN) \
-                         | (1 << SWFDEC_BUTTON_OVER_DOWN_TO_IDLE))) == 0);
-  }
-  if (movie->button->events)
-    swfdec_event_list_execute (movie->button->events, 
-	SWFDEC_AS_OBJECT (SWFDEC_MOVIE (movie)->parent), 
-	SWFDEC_SECURITY (SWFDEC_MOVIE (movie)->resource), condition, 0);
-  name = swfdec_button_condition_get_name (condition);
-  swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL, NULL);
-}
-
-#define CONTENT_IN_FRAME(content, frame) \
-  ((content)->sequence->start <= frame && \
-   (content)->sequence->end > frame)
-static void
-swfdec_button_movie_change_state (SwfdecButtonMovie *movie, SwfdecButtonState state)
-{
-  SwfdecMovie *mov = SWFDEC_MOVIE (movie);
-  GList *walk;
-
-  g_assert (movie->state != state);
-  SWFDEC_LOG ("changing state on button movie %p from %d to %d", movie,
-      movie->state, state);
-  /* do this in 2 loops - otherwise going down DOWN=>UP would
-   * remove children that are only in these 2 states (due to how
-   * adding them is handled)
-   */
-  for (walk = movie->button->records; walk; walk = walk->next) {
-    SwfdecContent *content = walk->data;
-    if (CONTENT_IN_FRAME (content, (guint) movie->state) &&
-	!CONTENT_IN_FRAME (content, (guint) state)) {
-      SwfdecMovie *child = swfdec_movie_find (mov, content->depth);
-      if (child)
-	swfdec_movie_remove (child);
-    }
-  }
-  for (walk = movie->button->records; walk; walk = walk->next) {
-    SwfdecContent *content = walk->data;
-    if (!CONTENT_IN_FRAME (content, (guint) movie->state) &&
-	CONTENT_IN_FRAME (content, (guint) state)) {
-      SwfdecMovie *child = swfdec_movie_find (mov, content->depth);
-      if (child) {
-	g_assert_not_reached ();
-      }
-      swfdec_movie_new_for_content (mov, content);
-    }
-  }
-  movie->state = state;
-}
-
-static void
-swfdec_button_movie_change_mouse (SwfdecButtonMovie *movie, gboolean mouse_in, int button)
-{
-  int event;
-  int sound;
-
-  if (movie->mouse_in == mouse_in &&
-      movie->mouse_button == button)
-    return;
-  SWFDEC_LOG ("changing mouse state %s: %s %s (%u) => %s %s (%u)", 
-      movie->button->menubutton ? "MENU" : "BUTTON",
-      movie->mouse_in ? "IN" : "OUT", movie->mouse_button ? "DOWN" : "UP",
-      (movie->mouse_in ? 2 : 0) + movie->mouse_button,
-      mouse_in ? "IN" : "OUT", button ? "DOWN" : "UP",
-      (mouse_in ? 2 : 0) + button);
-  event = event_table[movie->button->menubutton ? 1 : 0]
-		     [(movie->mouse_in ? 2 : 0) + movie->mouse_button]
-		     [(mouse_in ? 2 : 0) + button];
-
-#ifndef G_DISABLE_ASSERT
-  if (event == -1) {
-    g_error ("Unhandled event for %s: %u => %u",
-	movie->button->menubutton ? "menu" : "button",
-	(movie->mouse_in ? 2 : 0) + movie->mouse_button,
-	(mouse_in ? 2 : 0) + button);
-  }
-#endif
-  if (event >= 0) {
-    SWFDEC_LOG ("emitting event for condition %u", event);
-    swfdec_button_movie_execute (movie, event);
-  }
-  sound = sound_table[movie->button->menubutton ? 1 : 0]
-		     [(movie->mouse_in ? 2 : 0) + movie->mouse_button]
-		     [(mouse_in ? 2 : 0) + button];
-  if (sound >= 0 && movie->button->sounds[sound]) {
-    SwfdecAudio *audio;
-    SWFDEC_LOG ("playing button sound %d", sound);
-    audio = swfdec_audio_event_new_from_chunk (
-	SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context),
-	movie->button->sounds[sound]);
-    if (audio)
-      g_object_unref (audio);
-  }
-  movie->mouse_in = mouse_in;
-  movie->mouse_button = button;
-}
-#endif
-
 static void
 swfdec_button_movie_perform_place (SwfdecButtonMovie *button, SwfdecBits *bits)
 {
commit 231534c7e053d2a172d22a9c3651eaa0cdcbfdc1
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:33:02 2007 +0100

    booleans again...

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 26a68d2..a734d3b 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -372,10 +372,10 @@ swfdec_button_movie_mouse_release (SwfdecMovie *movie, guint button)
   SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
   player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
   if (player->mouse_below == movie) {
-    swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
-  } else {
     swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OVER);
     swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
+  } else {
+    swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
   }
 }
 
commit 69f1af529e3d5be22144cfa5786f2ca9e188418e
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:29:35 2007 +0100

    variable renames should be done completely

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 3cd38da..26a68d2 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -291,7 +291,7 @@ swfdec_button_movie_set_state (SwfdecButtonMovie *button, SwfdecButtonState stat
   /* remove all movies that aren't in the new state */
   new = 1 << state;
   if (button->state >= 0) {
-    old = 1 << movie->state;
+    old = 1 << button->state;
     for (walk = button->button->records; walk; walk = walk->next) {
       swfdec_bits_init (&bits, walk->data);
       i = swfdec_bits_get_u8 (&bits);
commit f0ca6978df945fe50dba023c460e90b267837150
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:27:16 2007 +0100

    boolean order confused

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index bb788fa..3cd38da 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -343,13 +343,13 @@ swfdec_button_movie_mouse_out (SwfdecMovie *movie)
   SwfdecButtonMovie *button = SWFDEC_BUTTON_MOVIE (movie);
   SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_out (movie);
   if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context))) {
-    swfdec_button_movie_set_state (button, SWFDEC_BUTTON_DOWN);
-  } else {
     if (button->button->menubutton) {
       swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
     } else {
       swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
     }
+  } else {
+    swfdec_button_movie_set_state (button, SWFDEC_BUTTON_UP);
   }
 }
 
commit ee2be49a0bd7c0965b57c923136d72ca20912605
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:26:03 2007 +0100

    remove unused variables

diff --git a/libswfdec/swfdec_button_movie.h b/libswfdec/swfdec_button_movie.h
index 16c2908..1f6dfaf 100644
--- a/libswfdec/swfdec_button_movie.h
+++ b/libswfdec/swfdec_button_movie.h
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -41,8 +41,6 @@ struct _SwfdecButtonMovie {
 
   SwfdecButton *	button;		/* button we render */
   SwfdecButtonState	state;		/* current state we're in */
-  gboolean		mouse_in;	/* TRUE if mouse was inside last we checked */
-  int			mouse_button;	/* last mouse button */
 };
 
 struct _SwfdecButtonMovieClass {
commit 8193b996d91d06293bc28751e14da6b9e8ab1e2c
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:24:03 2007 +0100

    first try at placing children clips

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 31ac954..bb788fa 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,7 +26,9 @@
 #include "swfdec_audio_event.h"
 #include "swfdec_debug.h"
 #include "swfdec_event.h"
+#include "swfdec_filter.h"
 #include "swfdec_player_internal.h"
+#include "swfdec_resource.h"
 
 G_DEFINE_TYPE (SwfdecButtonMovie, swfdec_button_movie, SWFDEC_TYPE_MOVIE)
 
@@ -204,14 +206,119 @@ swfdec_button_movie_change_mouse (SwfdecButtonMovie *movie, gboolean mouse_in, i
 #endif
 
 static void
-swfdec_button_movie_set_state (SwfdecButtonMovie *movie, SwfdecButtonState state)
+swfdec_button_movie_perform_place (SwfdecButtonMovie *button, SwfdecBits *bits)
 {
-  if (movie->state == state) {
+  SwfdecMovie *movie = SWFDEC_MOVIE (button);
+  gboolean has_blend_mode, has_filters, v2;
+  SwfdecColorTransform ctrans;
+  SwfdecGraphic *graphic;
+  SwfdecPlayer *player;
+  cairo_matrix_t trans;
+  guint id, blend_mode;
+  SwfdecMovie *new;
+  int depth;
+
+  swfdec_bits_getbits (bits, 2); /* reserved */
+  has_blend_mode = swfdec_bits_getbit (bits);
+  has_filters = swfdec_bits_getbit (bits);
+  SWFDEC_LOG ("  has_blend_mode = %d", has_blend_mode);
+  SWFDEC_LOG ("  has_filters = %d", has_filters);
+  swfdec_bits_getbits (bits, 4); /* states */
+  id = swfdec_bits_get_u16 (bits);
+  depth = swfdec_bits_get_u16 (bits);
+  depth -= 16384;
+  if (swfdec_movie_find (movie, depth)) {
+    SWFDEC_WARNING ("depth %d already occupied, skipping placement.", depth + 16384);
+    return;
+  }
+  graphic = swfdec_swf_decoder_get_character (SWFDEC_SWF_DECODER (movie->resource->decoder), id);
+  if (!SWFDEC_IS_GRAPHIC (graphic)) {
+    SWFDEC_ERROR ("id %u does not specify a graphic", id);
+    return;
+  }
+
+  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  new = swfdec_movie_new (player, depth, movie, movie->resource, graphic, NULL);
+  swfdec_bits_get_matrix (bits, &trans, NULL);
+  if (swfdec_bits_left (bits)) {
+    v2 = TRUE;
+    swfdec_bits_get_color_transform (bits, &ctrans);
+    if (has_blend_mode) {
+      blend_mode = swfdec_bits_get_u8 (bits);
+      SWFDEC_LOG ("  blend mode = %u", blend_mode);
+    } else {
+      blend_mode = 0;
+    }
+    if (has_filters) {
+      GSList *filters = swfdec_filter_parse (player, bits);
+      g_slist_free (filters);
+    }
+  } else {
+    /* DefineButton1 record */
+    v2 = FALSE;
+    if (has_blend_mode || has_filters) {
+      SWFDEC_ERROR ("cool, a DefineButton1 with filters or blend mode");
+    }
+    blend_mode = 0;
+  }
+  swfdec_movie_set_static_properties (new, &trans, v2 ? &ctrans : NULL, 0, 0, blend_mode, NULL);
+  swfdec_movie_queue_script (new, SWFDEC_EVENT_INITIALIZE);
+  swfdec_movie_queue_script (new, SWFDEC_EVENT_CONSTRUCT);
+  swfdec_movie_queue_script (new, SWFDEC_EVENT_LOAD);
+  swfdec_movie_initialize (new);
+  if (swfdec_bits_left (bits)) {
+    SWFDEC_WARNING ("button record for id %u has %u bytes left", id,
+	swfdec_bits_left (bits) / 8);
+  }
+}
+
+static void
+swfdec_button_movie_set_state (SwfdecButtonMovie *button, SwfdecButtonState state)
+{
+  SwfdecMovie *movie = SWFDEC_MOVIE (button);
+  SwfdecMovie *child;
+  SwfdecBits bits;
+  GSList *walk;
+  guint old, new, i;
+  int depth;
+
+  if (button->state == state) {
     SWFDEC_LOG ("not changing state, it's already in %d", state);
     return;
   }
-  SWFDEC_DEBUG ("changing state from %d to %d", movie->state, state);
-  movie->state = state;
+  SWFDEC_DEBUG ("changing state from %d to %d", button->state, state);
+  g_print ("changing state from %d to %d\n", button->state, state);
+  /* remove all movies that aren't in the new state */
+  new = 1 << state;
+  if (button->state >= 0) {
+    old = 1 << movie->state;
+    for (walk = button->button->records; walk; walk = walk->next) {
+      swfdec_bits_init (&bits, walk->data);
+      i = swfdec_bits_get_u8 (&bits);
+      if ((i & old) && !(i & new)) {
+	swfdec_bits_get_u16 (&bits);
+	depth = swfdec_bits_get_u16 (&bits);
+	child = swfdec_movie_find (movie, depth - 16384);
+	if (child) {
+	  swfdec_movie_remove (child);
+	} else {
+	  SWFDEC_WARNING ("no child at depth %d, none removed", depth);
+	}
+      }
+    }
+  } else {
+    /* to make sure that this never triggers when initializing */
+    old = 0;
+  }
+  button->state = state;
+  /* add all movies that are in the new state */
+  for (walk = button->button->records; walk; walk = walk->next) {
+    swfdec_bits_init (&bits, walk->data);
+    i = swfdec_bits_peek_u8 (&bits);
+    if ((i & old) || !(i & new))
+      continue;
+    swfdec_button_movie_perform_place (button, &bits);
+  }
 }
 
 static gboolean
commit 5347f0aecac6e3a8ea759d46c66e3903f0646378
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 21:23:20 2007 +0100

    buttons don't get all events

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index cb4e18a..8c86e58 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -419,6 +419,10 @@ swfdec_movie_execute (SwfdecMovie *movie, SwfdecEventType condition)
   g_return_if_fail (SWFDEC_IS_MOVIE (movie));
 
   /* special cases */
+  if (SWFDEC_IS_BUTTON_MOVIE (movie) && (
+	condition == SWFDEC_EVENT_CONSTRUCT || condition < SWFDEC_EVENT_PRESS))
+    return;
+
   if (condition == SWFDEC_EVENT_CONSTRUCT) {
     if (swfdec_movie_get_version (movie) <= 5)
       return;
commit 37b804f430cd36184bbc2b34aba947a1224e9072
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 16:09:38 2007 +0100

    include SWFDEC_GTK stuff, too

diff --git a/vivified/ui/Makefile.am b/vivified/ui/Makefile.am
index 4a28c90..0b63193 100644
--- a/vivified/ui/Makefile.am
+++ b/vivified/ui/Makefile.am
@@ -1,7 +1,7 @@
 noinst_PROGRAMS = vivified
 
-vivified_CFLAGS = $(GLOBAL_CFLAGS) $(VIVI_CFLAGS)
-vivified_LDFLAGS = $(VIVI_LIBS) 
+vivified_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_GTK_CFLAGS) $(VIVI_CFLAGS)
+vivified_LDFLAGS = $(VIVI_LIBS) $(SWFDEC_GTK_LIBS)
 vivified_LDADD = \
 	$(top_builddir)/vivified/core/libvivified-core.la \
 	$(top_builddir)/vivified/dock/libvivified-dock.la
commit 298d04af83173450499783845db51a2db33d14f6
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 11:42:43 2007 +0100

    implement state setting on mouse movements

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 742ea24..31ac954 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -26,6 +26,7 @@
 #include "swfdec_audio_event.h"
 #include "swfdec_debug.h"
 #include "swfdec_event.h"
+#include "swfdec_player_internal.h"
 
 G_DEFINE_TYPE (SwfdecButtonMovie, swfdec_button_movie, SWFDEC_TYPE_MOVIE)
 
@@ -203,11 +204,80 @@ swfdec_button_movie_change_mouse (SwfdecButtonMovie *movie, gboolean mouse_in, i
 #endif
 
 static void
+swfdec_button_movie_set_state (SwfdecButtonMovie *movie, SwfdecButtonState state)
+{
+  if (movie->state == state) {
+    SWFDEC_LOG ("not changing state, it's already in %d", state);
+    return;
+  }
+  SWFDEC_DEBUG ("changing state from %d to %d", movie->state, state);
+  movie->state = state;
+}
+
+static gboolean
+swfdec_button_movie_mouse_events (SwfdecMovie *movie)
+{
+  return TRUE;
+}
+
+static void
+swfdec_button_movie_mouse_in (SwfdecMovie *movie)
+{
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_in (movie);
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)))
+    swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_DOWN);
+  else
+    swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
+}
+
+static void
+swfdec_button_movie_mouse_out (SwfdecMovie *movie)
+{
+  SwfdecButtonMovie *button = SWFDEC_BUTTON_MOVIE (movie);
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_out (movie);
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context))) {
+    swfdec_button_movie_set_state (button, SWFDEC_BUTTON_DOWN);
+  } else {
+    if (button->button->menubutton) {
+      swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
+    } else {
+      swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
+    }
+  }
+}
+
+static void
+swfdec_button_movie_mouse_press (SwfdecMovie *movie, guint button)
+{
+  if (button != 0)
+    return;
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_press (movie, button);
+  swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_DOWN);
+}
+
+static void
+swfdec_button_movie_mouse_release (SwfdecMovie *movie, guint button)
+{
+  SwfdecPlayer *player;
+
+  if (button != 0)
+    return;
+  SWFDEC_MOVIE_CLASS (swfdec_button_movie_parent_class)->mouse_release (movie, button);
+  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  if (player->mouse_below == movie) {
+    swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_UP);
+  } else {
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OVER);
+    swfdec_button_movie_set_state (SWFDEC_BUTTON_MOVIE (movie), SWFDEC_BUTTON_OVER);
+  }
+}
+
+static void
 swfdec_button_movie_init_movie (SwfdecMovie *mov)
 {
-  //SwfdecButtonMovie *movie = SWFDEC_BUTTON_MOVIE (mov);
+  SwfdecButtonMovie *movie = SWFDEC_BUTTON_MOVIE (mov);
 
-  //swfdec_button_movie_change_state (movie, SWFDEC_BUTTON_UP);
+  swfdec_button_movie_set_state (movie, SWFDEC_BUTTON_UP);
 }
 
 #if 0
@@ -237,24 +307,6 @@ swfdec_button_movie_mouse_in (SwfdecMovie *movie, double x, double y)
   return FALSE;
 }
 
-static SwfdecButtonState
-swfdec_button_movie_get_state (SwfdecButtonMovie *movie, gboolean mouse_in, int button)
-{
-  if (button) {
-    if (mouse_in)
-      return SWFDEC_BUTTON_DOWN;
-    else if (movie->button->menubutton)
-      return SWFDEC_BUTTON_UP;
-    else
-      return SWFDEC_BUTTON_OVER;
-  } else {
-    if (mouse_in)
-      return SWFDEC_BUTTON_OVER;
-    else
-      return SWFDEC_BUTTON_UP;
-  }
-}
-
 static void G_GNUC_UNUSED
 swfdec_button_movie_mouse_change (SwfdecMovie *mov, double x, double y, 
     gboolean mouse_in, int button)
@@ -276,6 +328,12 @@ swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
 
   movie_class->init_movie = swfdec_button_movie_init_movie;
   movie_class->update_extents = swfdec_button_movie_update_extents;
+
+  movie_class->mouse_events = swfdec_button_movie_mouse_events;
+  movie_class->mouse_in = swfdec_button_movie_mouse_in;
+  movie_class->mouse_out = swfdec_button_movie_mouse_out;
+  movie_class->mouse_press = swfdec_button_movie_mouse_press;
+  movie_class->mouse_release = swfdec_button_movie_mouse_release;
 }
 
 static void
commit 7af10952231dae68e3c40a46cc4f14baa8573ce6
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 11:27:58 2007 +0100

    copy the event list when initializing the movie

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index f6b7919..ca2a1f3 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -64,10 +64,12 @@ swfdec_button_dispose (GObject *object)
 static SwfdecMovie *
 swfdec_button_create_movie (SwfdecGraphic *graphic, gsize *size)
 {
+  SwfdecButton *button = SWFDEC_BUTTON (graphic);
   SwfdecButtonMovie *movie = g_object_new (SWFDEC_TYPE_BUTTON_MOVIE, NULL);
 
-  movie->button = SWFDEC_BUTTON (graphic);
+  movie->button = button;
   *size = sizeof (SwfdecButtonMovie);
+  SWFDEC_MOVIE (movie)->events = swfdec_event_list_copy (button->events);
 
   return SWFDEC_MOVIE (movie);
 }
commit 7604bb27705b1b4391d914d673fd15fa77744f43
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 11:26:19 2007 +0100

    translate event types to the same types used by PlaceObject, so we can use the
    
    same code in both cases

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index 45972ec..f6b7919 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -83,6 +83,23 @@ swfdec_button_class_init (SwfdecButtonClass * g_class)
   graphic_class->create_movie = swfdec_button_create_movie;
 }
 
+static guint
+swfdec_button_translate_conditions (guint conditions)
+{
+  /* FIXME: This assumes IDLE<=>OVER_DOWN is the same as DRAG_OVER/OUT, is that correct? */
+  static const SwfdecEventType events[] = { SWFDEC_EVENT_ROLL_OVER, SWFDEC_EVENT_ROLL_OUT,
+    SWFDEC_EVENT_PRESS, SWFDEC_EVENT_RELEASE, SWFDEC_EVENT_DRAG_OUT, SWFDEC_EVENT_DRAG_OVER,
+    SWFDEC_EVENT_RELEASE_OUTSIDE, SWFDEC_EVENT_DRAG_OVER, SWFDEC_EVENT_DRAG_OUT };
+  guint i, ret;
+
+  ret = 0;
+  for (i = 0; i <= 8; i++) {
+    if (conditions & (1 << i))
+      ret |= events[i];
+  }
+  return ret;
+}
+
 int
 tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
 {
@@ -181,6 +198,7 @@ tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
     condition = swfdec_bits_get_u16 (&bits);
     key = condition >> 9;
     condition &= 0x1FF;
+    condition = swfdec_button_translate_conditions (condition);
 
     SWFDEC_LOG (" length = %d", length);
 
commit fe6bc108d88607b71b31dd546d51379c561d3244
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Nov 26 11:15:07 2007 +0100

    prepare event handling for buttons
    
    - don't allow setting an event list if it's not on a MovieClip
    - execute scripts on buttons, too and not jsut on movieclips

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index bc205eb..cb4e18a 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -459,7 +459,7 @@ swfdec_movie_queue_script (SwfdecMovie *movie, SwfdecEventType condition)
   
   g_return_if_fail (SWFDEC_IS_MOVIE (movie));
 
-  if (!SWFDEC_IS_SPRITE_MOVIE (movie))
+  if (!SWFDEC_IS_SPRITE_MOVIE (movie) && !SWFDEC_IS_BUTTON_MOVIE (movie))
     return;
 
   switch (condition) {
@@ -1537,9 +1537,13 @@ swfdec_movie_set_static_properties (SwfdecMovie *movie, const cairo_matrix_t *tr
     swfdec_movie_invalidate (movie);
   }
   if (events) {
-    if (movie->events)
-      swfdec_event_list_free (movie->events);
-    movie->events = swfdec_event_list_copy (events);
+    if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+      if (movie->events)
+	swfdec_event_list_free (movie->events);
+      movie->events = swfdec_event_list_copy (events);
+    } else {
+      SWFDEC_WARNING ("trying to set events on a %s, not allowed", G_OBJECT_TYPE_NAME (movie));
+    }
   }
 }
 
commit 7f5140eb76960d38721f94fca9029696674d2ce1
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 25 20:11:51 2007 +0100

    first step at rewriting the button code - nothing works, but it compiles

diff --git a/libswfdec/swfdec_button.c b/libswfdec/swfdec_button.c
index d537952..45972ec 100644
--- a/libswfdec/swfdec_button.c
+++ b/libswfdec/swfdec_button.c
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		      2006 Benjamin Otte <otte at gnome.org>
+ *		 2006-2007 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,6 +25,8 @@
 #include <string.h>
 #include "swfdec_button.h"
 #include "swfdec_button_movie.h"
+#include "swfdec_debug.h"
+#include "swfdec_filter.h"
 #include "swfdec_sound.h"
 #include "swfdec_sprite.h"
 
@@ -42,8 +44,9 @@ swfdec_button_dispose (GObject *object)
   guint i;
   SwfdecButton *button = SWFDEC_BUTTON (object);
 
-  g_list_foreach (button->records, (GFunc) swfdec_content_free, NULL);
-  g_list_free (button->records);
+  g_slist_foreach (button->records, (GFunc) swfdec_buffer_unref, NULL);
+  g_slist_free (button->records);
+  button->records = NULL;
   if (button->events != NULL) {
     swfdec_event_list_free (button->events);
     button->events = NULL;
@@ -80,3 +83,126 @@ swfdec_button_class_init (SwfdecButtonClass * g_class)
   graphic_class->create_movie = swfdec_button_create_movie;
 }
 
+int
+tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
+{
+  SwfdecBits bits;
+  int id, reserved;
+  guint length;
+  SwfdecButton *button;
+  char *script_name;
+
+  id = swfdec_bits_get_u16 (&s->b);
+  button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
+  if (!button)
+    return SWFDEC_STATUS_OK;
+
+  SWFDEC_LOG ("  ID: %d", id);
+
+  reserved = swfdec_bits_getbits (&s->b, 7);
+  button->menubutton = swfdec_bits_getbit (&s->b) ? TRUE : FALSE;
+  length = swfdec_bits_get_u16 (&s->b);
+
+  SWFDEC_LOG ("  reserved = %d", reserved);
+  SWFDEC_LOG ("  menu = %d", button->menubutton);
+  SWFDEC_LOG ("  length of region = %d", length);
+
+  if (length)
+    swfdec_bits_init_bits (&bits, &s->b, length > 2 ? length - 2 : 0);
+  else
+    swfdec_bits_init_bits (&bits, &s->b, swfdec_bits_left (&s->b) / 8);
+  while (swfdec_bits_peek_u8 (&bits)) {
+    SwfdecBits tmp;
+    SwfdecBuffer *buffer;
+    cairo_matrix_t trans;
+    SwfdecColorTransform ctrans;
+    guint states;
+    gboolean has_blend_mode, has_filters;
+
+    /* we parse the placement info into buffers each containing one palcement */
+    tmp = bits;
+
+    if (s->version >= 8) {
+      reserved = swfdec_bits_getbits (&bits, 2);
+      has_blend_mode = swfdec_bits_getbit (&bits);
+      has_filters = swfdec_bits_getbit (&bits);
+      SWFDEC_LOG ("  reserved = %d", reserved);
+      SWFDEC_LOG ("  has_blend_mode = %d", has_blend_mode);
+      SWFDEC_LOG ("  has_filters = %d", has_filters);
+    } else {
+      reserved = swfdec_bits_getbits (&bits, 4);
+      has_blend_mode = 0;
+      has_filters = 0;
+      SWFDEC_LOG ("  reserved = %d", reserved);
+    }
+    states = swfdec_bits_getbits (&bits, 4);
+    swfdec_bits_skip_bytes (&bits, 4);
+
+    SWFDEC_LOG ("  states: %s%s%s%s",
+        states & (1 << SWFDEC_BUTTON_HIT) ? "HIT " : "", 
+	states & (1 << SWFDEC_BUTTON_DOWN) ? "DOWN " : "", 
+        states & (1 << SWFDEC_BUTTON_OVER) ? "OVER " : "",
+	states & (1 << SWFDEC_BUTTON_UP) ? "UP " : "");
+
+    swfdec_bits_get_matrix (&bits, &trans, NULL);
+    SWFDEC_LOG ("matrix: %g %g  %g %g   %g %g",
+	trans.xx, trans.yy, 
+	trans.xy, trans.yx,
+	trans.x0, trans.y0);
+    swfdec_bits_get_color_transform (&bits, &ctrans);
+
+    if (has_filters) {
+      GSList *list = swfdec_filter_parse (SWFDEC_DECODER (s)->player, &bits);
+      g_slist_free (list);
+    }
+    if (has_blend_mode) {
+      guint blend_mode = swfdec_bits_get_u8 (&bits);
+      SWFDEC_LOG ("  blend mode = %u", blend_mode);
+    }
+    buffer = swfdec_bits_get_buffer (&tmp, (swfdec_bits_left (&tmp) - swfdec_bits_left (&bits)) / 8);
+    g_assert (buffer);
+    button->records = g_slist_prepend (button->records, buffer);
+  }
+  swfdec_bits_get_u8 (&bits);
+  if (swfdec_bits_left (&bits)) {
+    SWFDEC_WARNING ("%u bytes left when parsing button records", swfdec_bits_left (&bits) / 8);
+  }
+  button->records = g_slist_reverse (button->records);
+
+  script_name = g_strdup_printf ("Button%u", SWFDEC_CHARACTER (button)->id);
+  while (length != 0) {
+    guint condition, key;
+
+    length = swfdec_bits_get_u16 (&s->b);
+    if (length)
+      swfdec_bits_init_bits (&bits, &s->b, length > 2 ? length - 2 : 0);
+    else
+      swfdec_bits_init_bits (&bits, &s->b, swfdec_bits_left (&s->b) / 8);
+    condition = swfdec_bits_get_u16 (&bits);
+    key = condition >> 9;
+    condition &= 0x1FF;
+
+    SWFDEC_LOG (" length = %d", length);
+
+    if (button->events == NULL)
+      button->events = swfdec_event_list_new (SWFDEC_DECODER (s)->player);
+    SWFDEC_LOG ("  new event for condition %u (key %u)", condition, key);
+    swfdec_event_list_parse (button->events, &bits, s->version, condition, key,
+	script_name);
+    if (swfdec_bits_left (&bits)) {
+      SWFDEC_WARNING ("%u bytes left after parsing script", swfdec_bits_left (&bits) / 8);
+    }
+  }
+  g_free (script_name);
+
+  return SWFDEC_STATUS_OK;
+}
+
+int
+tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
+{
+  SWFDEC_ERROR ("implement DefineButton again");
+
+  return SWFDEC_STATUS_OK;
+}
+
diff --git a/libswfdec/swfdec_button.h b/libswfdec/swfdec_button.h
index 8baa88f..ddf5900 100644
--- a/libswfdec/swfdec_button.h
+++ b/libswfdec/swfdec_button.h
@@ -1,7 +1,7 @@
 /* Swfdec
  * Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
  *		 2005-2006 Eric Anholt <eric at anholt.net>
- *		      2006 Benjamin Otte <otte at gnome.org>
+ *		 2006-2007 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -62,7 +62,7 @@ struct _SwfdecButton {
 
   gboolean		menubutton;	/* treat as menubutton */
 
-  GList *		records;	/* the contained objects */
+  GSList *		records;	/* the contained objects */
   SwfdecEventList *	events;		/* the events triggered by this button */
   SwfdecSoundChunk *	sounds[4];    	/* for meaning of index see DefineButtonSound */
 };
@@ -72,8 +72,12 @@ struct _SwfdecButtonClass
   SwfdecGraphicClass	graphic_class;
 };
 
-GType		swfdec_button_get_type	(void);
+GType		swfdec_button_get_type	  	(void);
 
+int		tag_func_define_button		(SwfdecSwfDecoder *	s,
+						 guint			tag);
+int		tag_func_define_button_2	(SwfdecSwfDecoder *	s,
+						 guint			tag);
 
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index cb94b6a..742ea24 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -37,6 +37,7 @@ swfdec_button_movie_update_extents (SwfdecMovie *movie,
       &SWFDEC_GRAPHIC (SWFDEC_BUTTON_MOVIE (movie)->button)->extents);
 }
 
+#if 0
 /* first index is 1 for menubutton, second index is previous state,
  * last index is current state
  * MSB in index is mouse OUT = 0, IN = 1
@@ -199,15 +200,17 @@ swfdec_button_movie_change_mouse (SwfdecButtonMovie *movie, gboolean mouse_in, i
   movie->mouse_in = mouse_in;
   movie->mouse_button = button;
 }
+#endif
 
 static void
 swfdec_button_movie_init_movie (SwfdecMovie *mov)
 {
-  SwfdecButtonMovie *movie = SWFDEC_BUTTON_MOVIE (mov);
+  //SwfdecButtonMovie *movie = SWFDEC_BUTTON_MOVIE (mov);
 
-  swfdec_button_movie_change_state (movie, SWFDEC_BUTTON_UP);
+  //swfdec_button_movie_change_state (movie, SWFDEC_BUTTON_UP);
 }
 
+#if 0
 static gboolean G_GNUC_UNUSED
 swfdec_button_movie_mouse_in (SwfdecMovie *movie, double x, double y)
 {
@@ -264,6 +267,7 @@ swfdec_button_movie_mouse_change (SwfdecMovie *mov, double x, double y,
   }
   swfdec_button_movie_change_mouse (movie, mouse_in, button);
 }
+#endif
 
 static void
 swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
@@ -272,8 +276,6 @@ swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
 
   movie_class->init_movie = swfdec_button_movie_init_movie;
   movie_class->update_extents = swfdec_button_movie_update_extents;
-  //movie_class->mouse_in = swfdec_button_movie_mouse_in;
-  //movie_class->mouse_change = swfdec_button_movie_mouse_change;
 }
 
 static void
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index 5e0142e..692a0a0 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -253,77 +253,7 @@ tag_func_define_sprite (SwfdecSwfDecoder * s, guint define_sprite_tag)
   return SWFDEC_STATUS_OK;
 }
 
-#define CONTENT_IN_FRAME(content, frame) \
-  ((content)->sequence->start <= frame && \
-   (content)->sequence->end > frame)
-static guint
-swfdec_button_remove_duplicates (SwfdecButton *button, int depth, guint states)
-{
-  GList *walk;
-  guint taken = 0;
-  guint i;
-
-  /* 1) find out which states are already taken */
-  for (walk = button->records; walk; walk = walk->next) {
-    SwfdecContent *cur = walk->data;
-    if (cur->depth != depth)
-      continue;
-    for (i = 0; i < 4; i++) {
-      if (CONTENT_IN_FRAME (cur, i))
-	taken |= (1 << i);
-    }
-  }
-  /* 2) mark states that overlap */
-  taken &= states;
-  /* 3) remove the overlapping states */
-  if (taken) {
-    SWFDEC_ERROR ("overlapping contents in button, removing for depth %u and states %u",
-	depth, taken);
-    states &= ~taken;
-  }
-  return states;
-}
-
-static void
-swfdec_button_append_content (SwfdecButton *button, guint states, SwfdecContent *content)
-{
-  guint i;
-  SwfdecContent *cur = NULL;
-
-  states = swfdec_button_remove_duplicates (button, content->depth, states);
-
-  for (i = 0; i < 4; i++) {
-    if (!cur && (states & 1)) {
-      cur = content;
-      if (content->end != G_MAXUINT) {
-	/* need a copy here */
-	cur = swfdec_content_new (content->depth);
-	*cur = *content;
-	cur->sequence = cur;
-      }
-      cur->start = i;
-      button->records = g_list_append (button->records, cur);
-    }
-    if (cur && !(states & 1)) {
-      cur->end = i;
-      cur = NULL;
-    }
-    states >>= 1;
-  }
-  if (cur) {
-    SwfdecRect rect;
-    cur->end = 4;
-    swfdec_rect_transform (&rect, &content->graphic->extents, &cur->transform);
-    swfdec_rect_union (&SWFDEC_GRAPHIC (button)->extents,
-	&SWFDEC_GRAPHIC (button)->extents, &rect);
-  }
-  if (content->end == G_MAXUINT) {
-    SWFDEC_ERROR ("button record for graphic %u is not used in any state, discarding", 
-	SWFDEC_CHARACTER (content->graphic)->id);
-    swfdec_content_free (content);
-  }
-}
-
+#if 0
 static int
 tag_func_define_button_2 (SwfdecSwfDecoder * s, guint tag)
 {
@@ -505,6 +435,7 @@ tag_func_define_button (SwfdecSwfDecoder * s, guint tag)
 
   return SWFDEC_STATUS_OK;
 }
+#endif
 
 static int
 tag_func_file_attributes (SwfdecSwfDecoder *s, guint tag)
commit 09ea0dc2225e6f62c34d0a315fc109df4c75bee7
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 19:48:35 2007 +0100

    update tests to use act files that trigger more events

diff --git a/test/trace/mouse-movie-below-movie-5.swf.act b/test/trace/mouse-movie-below-movie-5.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-movie-5.swf.act
+++ b/test/trace/mouse-movie-below-movie-5.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-movie-6.swf.act b/test/trace/mouse-movie-below-movie-6.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-movie-6.swf.act
+++ b/test/trace/mouse-movie-below-movie-6.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-movie-6.swf.trace b/test/trace/mouse-movie-below-movie-6.swf.trace
index 8a25654..e00b5f3 100644
--- a/test/trace/mouse-movie-below-movie-6.swf.trace
+++ b/test/trace/mouse-movie-below-movie-6.swf.trace
@@ -1,5 +1,9 @@
 onRollOver: _level0.b
 onPress: _level0.b
 onDragOut: _level0.b
+onDragOver: _level0.b
+onRelease: _level0.b
+onPress: _level0.b
+onDragOut: _level0.b
 onReleaseOutside: _level0.b
 onRollOver: _level0.a
diff --git a/test/trace/mouse-movie-below-movie-7.swf.act b/test/trace/mouse-movie-below-movie-7.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-movie-7.swf.act
+++ b/test/trace/mouse-movie-below-movie-7.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-movie-7.swf.trace b/test/trace/mouse-movie-below-movie-7.swf.trace
index 8a25654..e00b5f3 100644
--- a/test/trace/mouse-movie-below-movie-7.swf.trace
+++ b/test/trace/mouse-movie-below-movie-7.swf.trace
@@ -1,5 +1,9 @@
 onRollOver: _level0.b
 onPress: _level0.b
 onDragOut: _level0.b
+onDragOver: _level0.b
+onRelease: _level0.b
+onPress: _level0.b
+onDragOut: _level0.b
 onReleaseOutside: _level0.b
 onRollOver: _level0.a
diff --git a/test/trace/mouse-movie-below-movie-8.swf.act b/test/trace/mouse-movie-below-movie-8.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-movie-8.swf.act
+++ b/test/trace/mouse-movie-below-movie-8.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-movie-8.swf.trace b/test/trace/mouse-movie-below-movie-8.swf.trace
index 8a25654..e00b5f3 100644
--- a/test/trace/mouse-movie-below-movie-8.swf.trace
+++ b/test/trace/mouse-movie-below-movie-8.swf.trace
@@ -1,5 +1,9 @@
 onRollOver: _level0.b
 onPress: _level0.b
 onDragOut: _level0.b
+onDragOver: _level0.b
+onRelease: _level0.b
+onPress: _level0.b
+onDragOut: _level0.b
 onReleaseOutside: _level0.b
 onRollOver: _level0.a
diff --git a/test/trace/mouse-movie-below-nonevent-movie-5.swf.act b/test/trace/mouse-movie-below-nonevent-movie-5.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-5.swf.act
+++ b/test/trace/mouse-movie-below-nonevent-movie-5.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-nonevent-movie-6.swf.act b/test/trace/mouse-movie-below-nonevent-movie-6.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-6.swf.act
+++ b/test/trace/mouse-movie-below-nonevent-movie-6.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace
index cdb17dd..0e55f00 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace
+++ b/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace
@@ -1,3 +1,5 @@
 onRollOver: _level0.a
 onPress: _level0.a
 onRelease: _level0.a
+onPress: _level0.a
+onRelease: _level0.a
diff --git a/test/trace/mouse-movie-below-nonevent-movie-7.swf.act b/test/trace/mouse-movie-below-nonevent-movie-7.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-7.swf.act
+++ b/test/trace/mouse-movie-below-nonevent-movie-7.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace
index cdb17dd..0e55f00 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace
+++ b/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace
@@ -1,3 +1,5 @@
 onRollOver: _level0.a
 onPress: _level0.a
 onRelease: _level0.a
+onPress: _level0.a
+onRelease: _level0.a
diff --git a/test/trace/mouse-movie-below-nonevent-movie-8.swf.act b/test/trace/mouse-movie-below-nonevent-movie-8.swf.act
index 80749b5..e1639d5 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-8.swf.act
+++ b/test/trace/mouse-movie-below-nonevent-movie-8.swf.act
@@ -1,9 +1,17 @@
-wait 1000
+wait 300
 move 50, 50
-wait 1000
+wait 300
 down
-wait 1000
+wait 300
 move 140, 140
-wait 1000
+wait 300
+move 50, 50
+wait 300
+up
+wait 300
+down
+wait 300
+move 140, 140
+wait 300
 up
-wait 1000
+wait 300
diff --git a/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace
index cdb17dd..0e55f00 100644
--- a/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace
+++ b/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace
@@ -1,3 +1,5 @@
 onRollOver: _level0.a
 onPress: _level0.a
 onRelease: _level0.a
+onPress: _level0.a
+onRelease: _level0.a
commit b26c8733189ab734f724da91dedf9b2f2d5a29a1
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 19:08:45 2007 +0100

    make get_movie_at return a non-event movie if it's below the mouse

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 966778e..bc205eb 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -644,7 +644,7 @@ swfdec_movie_get_mouse_events (SwfdecMovie *movie)
  * @movie: a #SwfdecMovie
  * @x: x coordinate in parent's coordinate space
  * @y: y coordinate in the parent's coordinate space
- * @events: %TRUE to only respect movies that receive events
+ * @events: %TRUE to only prefer movies that receive events
  *
  * Gets the child at the given coordinates. The coordinates are in the 
  * coordinate system of @movie's parent (or the global coordinate system for
@@ -670,8 +670,6 @@ swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y, gboolean even
   klass = SWFDEC_MOVIE_GET_CLASS (movie);
   g_return_val_if_fail (klass->contains, NULL);
   ret = klass->contains (movie, x, y, events);
-  if (events && ret && !swfdec_movie_get_mouse_events (ret))
-    ret = NULL;
 
   return ret;
 }
commit 4592c87e6d51ba2a62579cab0f97675fb4946a9a
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 14:08:25 2007 +0100

    add test checking addProperty properties are also relevant for mouse events

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 00ca5eb..6bc3116 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -1317,6 +1317,19 @@ EXTRA_DIST = \
 	microphone-properties-7.swf.trace \
 	microphone-properties-8.swf \
 	microphone-properties-8.swf.trace \
+	mouse-addProperty-relevant.as \
+	mouse-addProperty-relevant-5.swf \
+	mouse-addProperty-relevant-5.swf.act \
+	mouse-addProperty-relevant-5.swf.trace \
+	mouse-addProperty-relevant-6.swf \
+	mouse-addProperty-relevant-6.swf.act \
+	mouse-addProperty-relevant-6.swf.trace \
+	mouse-addProperty-relevant-7.swf \
+	mouse-addProperty-relevant-7.swf.act \
+	mouse-addProperty-relevant-7.swf.trace \
+	mouse-addProperty-relevant-8.swf \
+	mouse-addProperty-relevant-8.swf.act \
+	mouse-addProperty-relevant-8.swf.trace \
 	mouse-movie-below-movie.as \
 	mouse-movie-below-movie-5.swf \
 	mouse-movie-below-movie-5.swf.act \
diff --git a/test/trace/mouse-addProperty-relevant-5.swf b/test/trace/mouse-addProperty-relevant-5.swf
new file mode 100644
index 0000000..b1b6ab1
Binary files /dev/null and b/test/trace/mouse-addProperty-relevant-5.swf differ
diff --git a/test/trace/mouse-addProperty-relevant-5.swf.act b/test/trace/mouse-addProperty-relevant-5.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-5.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-addProperty-relevant-5.swf.trace b/test/trace/mouse-addProperty-relevant-5.swf.trace
new file mode 100644
index 0000000..1062378
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-5.swf.trace
@@ -0,0 +1 @@
+Check if addProperty proeprties make movies sensitive to mouse events
diff --git a/test/trace/mouse-addProperty-relevant-6.swf b/test/trace/mouse-addProperty-relevant-6.swf
new file mode 100644
index 0000000..0465358
Binary files /dev/null and b/test/trace/mouse-addProperty-relevant-6.swf differ
diff --git a/test/trace/mouse-addProperty-relevant-6.swf.act b/test/trace/mouse-addProperty-relevant-6.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-6.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-addProperty-relevant-6.swf.trace b/test/trace/mouse-addProperty-relevant-6.swf.trace
new file mode 100644
index 0000000..d235e29
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-6.swf.trace
@@ -0,0 +1,3 @@
+Check if addProperty proeprties make movies sensitive to mouse events
+onRollOver: _level0.b
+onRollOver: _level0.a
diff --git a/test/trace/mouse-addProperty-relevant-7.swf b/test/trace/mouse-addProperty-relevant-7.swf
new file mode 100644
index 0000000..194d5df
Binary files /dev/null and b/test/trace/mouse-addProperty-relevant-7.swf differ
diff --git a/test/trace/mouse-addProperty-relevant-7.swf.act b/test/trace/mouse-addProperty-relevant-7.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-7.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-addProperty-relevant-7.swf.trace b/test/trace/mouse-addProperty-relevant-7.swf.trace
new file mode 100644
index 0000000..d235e29
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-7.swf.trace
@@ -0,0 +1,3 @@
+Check if addProperty proeprties make movies sensitive to mouse events
+onRollOver: _level0.b
+onRollOver: _level0.a
diff --git a/test/trace/mouse-addProperty-relevant-8.swf b/test/trace/mouse-addProperty-relevant-8.swf
new file mode 100644
index 0000000..64e4382
Binary files /dev/null and b/test/trace/mouse-addProperty-relevant-8.swf differ
diff --git a/test/trace/mouse-addProperty-relevant-8.swf.act b/test/trace/mouse-addProperty-relevant-8.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-8.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-addProperty-relevant-8.swf.trace b/test/trace/mouse-addProperty-relevant-8.swf.trace
new file mode 100644
index 0000000..d235e29
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant-8.swf.trace
@@ -0,0 +1,3 @@
+Check if addProperty proeprties make movies sensitive to mouse events
+onRollOver: _level0.b
+onRollOver: _level0.a
diff --git a/test/trace/mouse-addProperty-relevant.as b/test/trace/mouse-addProperty-relevant.as
new file mode 100644
index 0000000..a96d29e
--- /dev/null
+++ b/test/trace/mouse-addProperty-relevant.as
@@ -0,0 +1,23 @@
+// makeswf -v 7 -s 200x150 -r 1 -o mouse-addProperty-relevant.swf mouse-addProperty-relevant.as
+
+trace ("Check if addProperty proeprties make movies sensitive to mouse events");
+
+rectangle = function (mc, color, x, y, w, h) {
+  mc.beginFill (color);
+  mc.moveTo (x, y);
+  mc.lineTo (x, y + h);
+  mc.lineTo (x + w, y + h);
+  mc.lineTo (x + w, y);
+  mc.lineTo (x, y);
+  mc.endFill ();
+};
+
+install = function (mc) {
+  mc.addProperty ("onRollOver", function () { trace ("onRollOver: " + this); }, null);
+};
+
+install (Object.prototype);
+createEmptyMovieClip ("a", 0);
+createEmptyMovieClip ("b", 1);
+rectangle (a, 0, 0, 0, 200, 150);
+rectangle (b, 0xFF, 25, 25, 100, 100);
commit 10cc9a748cd4d08ff8ca0aeeaed31d369178b331
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 14:06:45 2007 +0100

    Check onUnload handling for correctness

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index d2c70f6..00ca5eb 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -1617,6 +1617,15 @@ EXTRA_DIST = \
 	onresize-7.swf.trace \
 	onresize-8.swf \
 	onresize-8.swf.trace \
+	onUnload-prototype.as \
+	onUnload-prototype-5.swf \
+	onUnload-prototype-5.swf.trace \
+	onUnload-prototype-6.swf \
+	onUnload-prototype-6.swf.trace \
+	onUnload-prototype-7.swf \
+	onUnload-prototype-7.swf.trace \
+	onUnload-prototype-8.swf \
+	onUnload-prototype-8.swf.trace \
 	order.swf \
 	order.swf.trace \
 	parent-root.swf \
diff --git a/test/trace/onUnload-prototype-5.swf b/test/trace/onUnload-prototype-5.swf
new file mode 100644
index 0000000..b3a53f1
Binary files /dev/null and b/test/trace/onUnload-prototype-5.swf differ
diff --git a/test/trace/onUnload-prototype-5.swf.trace b/test/trace/onUnload-prototype-5.swf.trace
new file mode 100644
index 0000000..b725abc
--- /dev/null
+++ b/test/trace/onUnload-prototype-5.swf.trace
@@ -0,0 +1,4 @@
+check onUnload even gets called when only defined on the prototype.
+done with 
+done with 
+done with 
diff --git a/test/trace/onUnload-prototype-6.swf b/test/trace/onUnload-prototype-6.swf
new file mode 100644
index 0000000..15853aa
Binary files /dev/null and b/test/trace/onUnload-prototype-6.swf differ
diff --git a/test/trace/onUnload-prototype-6.swf.trace b/test/trace/onUnload-prototype-6.swf.trace
new file mode 100644
index 0000000..845e50c
--- /dev/null
+++ b/test/trace/onUnload-prototype-6.swf.trace
@@ -0,0 +1,4 @@
+check onUnload even gets called when only defined on the prototype.
+done with _level0.a
+done with 
+done with _level0.c
diff --git a/test/trace/onUnload-prototype-7.swf b/test/trace/onUnload-prototype-7.swf
new file mode 100644
index 0000000..3cc8f4a
Binary files /dev/null and b/test/trace/onUnload-prototype-7.swf differ
diff --git a/test/trace/onUnload-prototype-7.swf.trace b/test/trace/onUnload-prototype-7.swf.trace
new file mode 100644
index 0000000..bcaa63b
--- /dev/null
+++ b/test/trace/onUnload-prototype-7.swf.trace
@@ -0,0 +1,4 @@
+check onUnload even gets called when only defined on the prototype.
+done with _level0.a
+done with undefined
+done with _level0.c
diff --git a/test/trace/onUnload-prototype-8.swf b/test/trace/onUnload-prototype-8.swf
new file mode 100644
index 0000000..8b9c459
Binary files /dev/null and b/test/trace/onUnload-prototype-8.swf differ
diff --git a/test/trace/onUnload-prototype-8.swf.trace b/test/trace/onUnload-prototype-8.swf.trace
new file mode 100644
index 0000000..bcaa63b
--- /dev/null
+++ b/test/trace/onUnload-prototype-8.swf.trace
@@ -0,0 +1,4 @@
+check onUnload even gets called when only defined on the prototype.
+done with _level0.a
+done with undefined
+done with _level0.c
diff --git a/test/trace/onUnload-prototype.as b/test/trace/onUnload-prototype.as
new file mode 100644
index 0000000..8df8e7b
--- /dev/null
+++ b/test/trace/onUnload-prototype.as
@@ -0,0 +1,17 @@
+// makeswf -v 7 -s 200x150 -r 1 -o onUnload-prototype.swf onUnload-prototype.as
+
+trace ("check onUnload even gets called when only defined on the prototype.");
+
+MovieClip.prototype.onUnload = function () { trace ("unload " + this); };
+createEmptyMovieClip ("a", 0);
+a.removeMovieClip ();
+trace ("done with " + a);
+delete MovieClip.prototype.onUnload;
+createEmptyMovieClip ("b", 0);
+b.removeMovieClip ();
+trace ("done with " + b);
+MovieClip.prototype.onUnload = 42;
+createEmptyMovieClip ("c", 0);
+c.removeMovieClip ();
+trace ("done with " + c);
+loadMovie ("fscommand:QUIT", "");
commit 92c9c506c3824a7afe4aa07eb528bf20e521310a
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 14:03:31 2007 +0100

    remove swfdec_as_object_has_function()
    
    replace calls to it with swfdec_as_object_has_variable

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 5ecfa1d..d1995c8 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -1250,30 +1250,6 @@ swfdec_as_object_call (SwfdecAsObject *object, const char *name, guint argc,
 }
 
 /**
- * swfdec_as_object_has_function:
- * @object: a #SwfdecAsObject
- * @name: garbage-collected name of th function
- *
- * Convenience function that checks of @object has a variable that references 
- * a function.
- *
- * Returns: %TRUE if object.name is a function.
- **/
-gboolean
-swfdec_as_object_has_function (SwfdecAsObject *object, const char *name)
-{
-  SwfdecAsValue val;
-
-  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), FALSE);
-  g_return_val_if_fail (name != NULL, FALSE);
-
-  swfdec_as_object_get_variable (object, name, &val);
-  if (!SWFDEC_AS_VALUE_IS_OBJECT (&val))
-    return FALSE;
-  return SWFDEC_IS_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (&val));
-}
-
-/**
  * swfdec_as_object_create:
  * @fun: constructor
  * @n_args: number of arguments
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index f32723d..a8b4379 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -176,8 +176,6 @@ SwfdecAsFunction *swfdec_as_object_add_constructor
 						 guint			min_args,
 						 SwfdecAsObject *	prototype);
 
-gboolean	swfdec_as_object_has_function	(SwfdecAsObject *       object,
-						 const char *		name);
 void		swfdec_as_object_call		(SwfdecAsObject *       object,
 						 const char *		name,
 						 guint			argc,
commit 6a63d325d02a7edf1d89485780928fa643454149
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 11:00:57 2007 +0100

    add a test similar to the last - only this time the upper movie receives events

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 3aa3dc7..d2c70f6 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -1317,6 +1317,19 @@ EXTRA_DIST = \
 	microphone-properties-7.swf.trace \
 	microphone-properties-8.swf \
 	microphone-properties-8.swf.trace \
+	mouse-movie-below-movie.as \
+	mouse-movie-below-movie-5.swf \
+	mouse-movie-below-movie-5.swf.act \
+	mouse-movie-below-movie-5.swf.trace \
+	mouse-movie-below-movie-6.swf \
+	mouse-movie-below-movie-6.swf.act \
+	mouse-movie-below-movie-6.swf.trace \
+	mouse-movie-below-movie-7.swf \
+	mouse-movie-below-movie-7.swf.act \
+	mouse-movie-below-movie-7.swf.trace \
+	mouse-movie-below-movie-8.swf \
+	mouse-movie-below-movie-8.swf.act \
+	mouse-movie-below-movie-8.swf.trace \
 	mouse-movie-below-nonevent-movie.as \
 	mouse-movie-below-nonevent-movie-5.swf \
 	mouse-movie-below-nonevent-movie-5.swf.act \
diff --git a/test/trace/mouse-movie-below-movie-5.swf b/test/trace/mouse-movie-below-movie-5.swf
new file mode 100644
index 0000000..c1dc29a
Binary files /dev/null and b/test/trace/mouse-movie-below-movie-5.swf differ
diff --git a/test/trace/mouse-movie-below-movie-5.swf.act b/test/trace/mouse-movie-below-movie-5.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-5.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-movie-5.swf.trace b/test/trace/mouse-movie-below-movie-5.swf.trace
new file mode 100644
index 0000000..e69de29
diff --git a/test/trace/mouse-movie-below-movie-6.swf b/test/trace/mouse-movie-below-movie-6.swf
new file mode 100644
index 0000000..f4d0029
Binary files /dev/null and b/test/trace/mouse-movie-below-movie-6.swf differ
diff --git a/test/trace/mouse-movie-below-movie-6.swf.act b/test/trace/mouse-movie-below-movie-6.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-6.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-movie-6.swf.trace b/test/trace/mouse-movie-below-movie-6.swf.trace
new file mode 100644
index 0000000..8a25654
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-6.swf.trace
@@ -0,0 +1,5 @@
+onRollOver: _level0.b
+onPress: _level0.b
+onDragOut: _level0.b
+onReleaseOutside: _level0.b
+onRollOver: _level0.a
diff --git a/test/trace/mouse-movie-below-movie-7.swf b/test/trace/mouse-movie-below-movie-7.swf
new file mode 100644
index 0000000..360c233
Binary files /dev/null and b/test/trace/mouse-movie-below-movie-7.swf differ
diff --git a/test/trace/mouse-movie-below-movie-7.swf.act b/test/trace/mouse-movie-below-movie-7.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-7.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-movie-7.swf.trace b/test/trace/mouse-movie-below-movie-7.swf.trace
new file mode 100644
index 0000000..8a25654
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-7.swf.trace
@@ -0,0 +1,5 @@
+onRollOver: _level0.b
+onPress: _level0.b
+onDragOut: _level0.b
+onReleaseOutside: _level0.b
+onRollOver: _level0.a
diff --git a/test/trace/mouse-movie-below-movie-8.swf b/test/trace/mouse-movie-below-movie-8.swf
new file mode 100644
index 0000000..db943f2
Binary files /dev/null and b/test/trace/mouse-movie-below-movie-8.swf differ
diff --git a/test/trace/mouse-movie-below-movie-8.swf.act b/test/trace/mouse-movie-below-movie-8.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-8.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-movie-8.swf.trace b/test/trace/mouse-movie-below-movie-8.swf.trace
new file mode 100644
index 0000000..8a25654
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie-8.swf.trace
@@ -0,0 +1,5 @@
+onRollOver: _level0.b
+onPress: _level0.b
+onDragOut: _level0.b
+onReleaseOutside: _level0.b
+onRollOver: _level0.a
diff --git a/test/trace/mouse-movie-below-movie.as b/test/trace/mouse-movie-below-movie.as
new file mode 100644
index 0000000..29d83b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-movie.as
@@ -0,0 +1,27 @@
+// makeswf -v 7 -s 200x150 -r 1 -o mouse-movie-below-movie.swf mouse-movie-below-movie.as
+
+rectangle = function (mc, color, x, y, w, h) {
+  mc.beginFill (color);
+  mc.moveTo (x, y);
+  mc.lineTo (x, y + h);
+  mc.lineTo (x + w, y + h);
+  mc.lineTo (x + w, y);
+  mc.lineTo (x, y);
+  mc.endFill ();
+};
+
+install = function (mc) {
+  mc.onRollOver = function () { trace ("onRollOver: " + this); };
+  mc.onRollOut = function () { trace ("onRollOut: " + this); };
+  mc.onDragOut = function () { trace ("onDragOut: " + this); };
+  mc.onDragOver = function () { trace ("onDragOver: " + this); };
+  mc.onPress = function () { trace ("onPress: " + this); };
+  mc.onRelease = function () { trace ("onRelease: " + this); };
+  mc.onReleaseOutside = function () { trace ("onReleaseOutside: " + this); };
+};
+
+createEmptyMovieClip ("a", 0);
+install (MovieClip.prototype);
+createEmptyMovieClip ("b", 1);
+rectangle (a, 0, 0, 0, 200, 150);
+rectangle (b, 0xFF, 25, 25, 100, 100);
commit a2236e6cac2ffe401de879e2d70962b498b1f71a
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 10:59:05 2007 +0100

    emit a mouse-in event after a mouse release outside the grab widget

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 0fe6f66..f6f89b9 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1129,8 +1129,14 @@ swfdec_player_do_mouse_release (SwfdecPlayer *player, guint button)
     SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
     if (klass->mouse_release)
       klass->mouse_release (player->mouse_grab, button);
-    if (button == 0)
+    if (button == 0 && player->mouse_grab != player->mouse_below) {
       player->mouse_grab = player->mouse_below;
+      if (player->mouse_grab) {
+	klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
+	if (klass->mouse_in)
+	  klass->mouse_in (player->mouse_grab);
+      }
+    }
   }
 
   /* FIXME: allow events to pass through */
commit 2069e72cfbf88475be80c8adbb0ebef7b74ead82
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Nov 23 10:48:54 2007 +0100

    add mouse movement test

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 091618c..3aa3dc7 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -1317,6 +1317,19 @@ EXTRA_DIST = \
 	microphone-properties-7.swf.trace \
 	microphone-properties-8.swf \
 	microphone-properties-8.swf.trace \
+	mouse-movie-below-nonevent-movie.as \
+	mouse-movie-below-nonevent-movie-5.swf \
+	mouse-movie-below-nonevent-movie-5.swf.act \
+	mouse-movie-below-nonevent-movie-5.swf.trace \
+	mouse-movie-below-nonevent-movie-6.swf \
+	mouse-movie-below-nonevent-movie-6.swf.act \
+	mouse-movie-below-nonevent-movie-6.swf.trace \
+	mouse-movie-below-nonevent-movie-7.swf \
+	mouse-movie-below-nonevent-movie-7.swf.act \
+	mouse-movie-below-nonevent-movie-7.swf.trace \
+	mouse-movie-below-nonevent-movie-8.swf \
+	mouse-movie-below-nonevent-movie-8.swf.act \
+	mouse-movie-below-nonevent-movie-8.swf.trace \
 	mouse-properties.as \
 	mouse-properties-5.swf \
 	mouse-properties-5.swf.trace \
diff --git a/test/trace/mouse-movie-below-nonevent-movie-5.swf b/test/trace/mouse-movie-below-nonevent-movie-5.swf
new file mode 100644
index 0000000..587cc3d
Binary files /dev/null and b/test/trace/mouse-movie-below-nonevent-movie-5.swf differ
diff --git a/test/trace/mouse-movie-below-nonevent-movie-5.swf.act b/test/trace/mouse-movie-below-nonevent-movie-5.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-5.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-nonevent-movie-5.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-5.swf.trace
new file mode 100644
index 0000000..e69de29
diff --git a/test/trace/mouse-movie-below-nonevent-movie-6.swf b/test/trace/mouse-movie-below-nonevent-movie-6.swf
new file mode 100644
index 0000000..b95bc02
Binary files /dev/null and b/test/trace/mouse-movie-below-nonevent-movie-6.swf differ
diff --git a/test/trace/mouse-movie-below-nonevent-movie-6.swf.act b/test/trace/mouse-movie-below-nonevent-movie-6.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-6.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace
new file mode 100644
index 0000000..cdb17dd
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-6.swf.trace
@@ -0,0 +1,3 @@
+onRollOver: _level0.a
+onPress: _level0.a
+onRelease: _level0.a
diff --git a/test/trace/mouse-movie-below-nonevent-movie-7.swf b/test/trace/mouse-movie-below-nonevent-movie-7.swf
new file mode 100644
index 0000000..f6aed05
Binary files /dev/null and b/test/trace/mouse-movie-below-nonevent-movie-7.swf differ
diff --git a/test/trace/mouse-movie-below-nonevent-movie-7.swf.act b/test/trace/mouse-movie-below-nonevent-movie-7.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-7.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace
new file mode 100644
index 0000000..cdb17dd
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-7.swf.trace
@@ -0,0 +1,3 @@
+onRollOver: _level0.a
+onPress: _level0.a
+onRelease: _level0.a
diff --git a/test/trace/mouse-movie-below-nonevent-movie-8.swf b/test/trace/mouse-movie-below-nonevent-movie-8.swf
new file mode 100644
index 0000000..2065974
Binary files /dev/null and b/test/trace/mouse-movie-below-nonevent-movie-8.swf differ
diff --git a/test/trace/mouse-movie-below-nonevent-movie-8.swf.act b/test/trace/mouse-movie-below-nonevent-movie-8.swf.act
new file mode 100644
index 0000000..80749b5
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-8.swf.act
@@ -0,0 +1,9 @@
+wait 1000
+move 50, 50
+wait 1000
+down
+wait 1000
+move 140, 140
+wait 1000
+up
+wait 1000
diff --git a/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace b/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace
new file mode 100644
index 0000000..cdb17dd
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie-8.swf.trace
@@ -0,0 +1,3 @@
+onRollOver: _level0.a
+onPress: _level0.a
+onRelease: _level0.a
diff --git a/test/trace/mouse-movie-below-nonevent-movie.as b/test/trace/mouse-movie-below-nonevent-movie.as
new file mode 100644
index 0000000..6654cf1
--- /dev/null
+++ b/test/trace/mouse-movie-below-nonevent-movie.as
@@ -0,0 +1,27 @@
+// makeswf -v 7 -s 200x150 -r 1 -o mouse-movie-below-nonevent-movie.swf mouse-movie-below-nonevent-movie.as
+
+rectangle = function (mc, color, x, y, w, h) {
+  mc.beginFill (color);
+  mc.moveTo (x, y);
+  mc.lineTo (x, y + h);
+  mc.lineTo (x + w, y + h);
+  mc.lineTo (x + w, y);
+  mc.lineTo (x, y);
+  mc.endFill ();
+};
+
+install = function (mc) {
+  mc.onRollOver = function () { trace ("onRollOver: " + this); };
+  mc.onRollOut = function () { trace ("onRollOut: " + this); };
+  mc.onDragOut = function () { trace ("onRollOut: " + this); };
+  mc.onDragOver = function () { trace ("onDragOver: " + this); };
+  mc.onPress = function () { trace ("onPress: " + this); };
+  mc.onRelease = function () { trace ("onRelease: " + this); };
+  mc.onReleaseOutside = function () { trace ("onReleaseOutside: " + this); };
+};
+
+createEmptyMovieClip ("a", 0);
+install (a);
+createEmptyMovieClip ("b", 1);
+rectangle (a, 0, 0, 0, 200, 150);
+rectangle (b, 0xFF, 25, 25, 100, 100);
commit b489d3114cef8256d860a6f5c44ad604661f7396
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 23:13:47 2007 +0100

    port to new API

diff --git a/vivified/ui/vivi_widget.c b/vivified/ui/vivi_widget.c
index e0ca455..6114e2c 100644
--- a/vivified/ui/vivi_widget.c
+++ b/vivified/ui/vivi_widget.c
@@ -102,12 +102,17 @@ vivi_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
 	vivi_widget_invalidate_click_area (debug);
 	debug->x = event->x;
 	debug->y = event->y;
-	swfdec_player_handle_mouse (player, debug->x, debug->y, debug->button);
+	swfdec_player_mouse_move (player, debug->x, debug->y);
 	vivi_widget_invalidate_click_area (debug);
 	break;
       case GDK_2BUTTON_PRESS:
 	debug->button = 1 - debug->button;
-	swfdec_player_handle_mouse (player, debug->x, debug->y, debug->button);
+	debug->x = event->x;
+	debug->y = event->y;
+	if (debug->button)
+	  swfdec_player_mouse_press (player, debug->x, debug->y, 1);
+	else
+	  swfdec_player_mouse_release (player, debug->x, debug->y, 1);
 	vivi_widget_invalidate_click_area (debug);
 	break;
       default:
commit a82b6bcfb6cda2f6cf2441f72eed8f74933dc164
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 21:23:30 2007 +0100

    fix to new mouse API

diff --git a/test/trace/swfdec_interaction.c b/test/trace/swfdec_interaction.c
index dd70ddd..cb940b9 100644
--- a/test/trace/swfdec_interaction.c
+++ b/test/trace/swfdec_interaction.c
@@ -66,11 +66,11 @@ swfdec_interaction_scanner_message (GScanner *scanner, gchar *message, gboolean
 }
 
 static void
-swfdec_command_append_mouse (SwfdecInteraction *inter, int x, int y, int button)
+swfdec_command_append_mouse (SwfdecInteraction *inter, SwfdecCommandType type, int x, int y, int button)
 {
   SwfdecCommand command;
 
-  command.command = SWFDEC_COMMAND_MOVE;
+  command.command = type;
   command.args.mouse.x = x;
   command.args.mouse.y = y;
   command.args.mouse.button = button;
@@ -151,13 +151,13 @@ swfdec_interaction_new (const char *data, guint length, GError **error)
 	  goto error;
 	}
 	j = scanner->value.v_int;
-	swfdec_command_append_mouse (inter, i, j, inter->mouse_button);
+	swfdec_command_append_mouse (inter, SWFDEC_COMMAND_MOVE, i, j, inter->mouse_button);
 	break;
       case SWFDEC_COMMAND_DOWN:
-	swfdec_command_append_mouse (inter, inter->mouse_x, inter->mouse_y, 1);
+	swfdec_command_append_mouse (inter, SWFDEC_COMMAND_DOWN, inter->mouse_x, inter->mouse_y, 1);
 	break;
       case SWFDEC_COMMAND_UP:
-	swfdec_command_append_mouse (inter, inter->mouse_x, inter->mouse_y, 0);
+	swfdec_command_append_mouse (inter, SWFDEC_COMMAND_UP, inter->mouse_x, inter->mouse_y, 1);
 	break;
       case SWFDEC_COMMAND_PRESS:
       case SWFDEC_COMMAND_RELEASE:
@@ -246,8 +246,8 @@ swfdec_interaction_advance (SwfdecInteraction *inter, SwfdecPlayer *player, guin
 	inter->time_elapsed -= command->args.time;
 	break;
       case SWFDEC_COMMAND_MOVE:
-	swfdec_player_handle_mouse (player, command->args.mouse.x, 
-	    command->args.mouse.y, command->args.mouse.button);
+	swfdec_player_mouse_move (player, command->args.mouse.x, 
+	    command->args.mouse.y);
 	break;
       case SWFDEC_COMMAND_PRESS:
 	swfdec_player_key_press (player, command->args.key.code, command->args.key.ascii);
@@ -255,9 +255,14 @@ swfdec_interaction_advance (SwfdecInteraction *inter, SwfdecPlayer *player, guin
       case SWFDEC_COMMAND_RELEASE:
 	swfdec_player_key_release (player, command->args.key.code, command->args.key.ascii);
 	break;
-      case SWFDEC_COMMAND_UP:
       case SWFDEC_COMMAND_DOWN:
-	/* these 2 get synthetisized into SWFDEC_COMMAND_MOVE */
+	swfdec_player_mouse_press (player, command->args.mouse.x, 
+	    command->args.mouse.y, command->args.mouse.button);
+	break;
+      case SWFDEC_COMMAND_UP:
+	swfdec_player_mouse_release (player, command->args.mouse.x, 
+	    command->args.mouse.y, command->args.mouse.button);
+	break;
       default:
 	g_assert_not_reached ();
 	return;
commit 237df78d99b522b9ca6af3230a954017328bc46e
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 16:53:29 2007 +0100

    implement mouse_events vfunc
    
    required adding swfdec_event_list_get_mouse_events()

diff --git a/libswfdec/swfdec_event.c b/libswfdec/swfdec_event.c
index c368ae3..585a5e0 100644
--- a/libswfdec/swfdec_event.c
+++ b/libswfdec/swfdec_event.c
@@ -215,3 +215,18 @@ swfdec_event_list_has_conditions (SwfdecEventList *list, SwfdecAsObject *object,
   return FALSE;
 }
 
+#define MOUSE_EVENTS 0x1FC0
+gboolean
+swfdec_event_list_has_mouse_events (SwfdecEventList *list)
+{
+  guint i;
+
+  g_return_val_if_fail (list != NULL, FALSE);
+
+  for (i = 0; i < list->events->len; i++) {
+    SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
+    if (event->conditions & MOUSE_EVENTS)
+      return TRUE;
+  }
+  return FALSE;
+}
diff --git a/libswfdec/swfdec_event.h b/libswfdec/swfdec_event.h
index 0e51f0a..7ac6857 100644
--- a/libswfdec/swfdec_event.h
+++ b/libswfdec/swfdec_event.h
@@ -71,6 +71,7 @@ gboolean		swfdec_event_list_has_conditions(SwfdecEventList *    list,
 							 SwfdecAsObject *     object,
 							 guint		      conditions,
 							 guint8		      key);
+gboolean		swfdec_event_list_has_mouse_events(SwfdecEventList *  list);
 							 
 
 G_END_DECLS
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 620a42b..966778e 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -1273,7 +1273,25 @@ swfdec_movie_do_render (SwfdecMovie *movie, cairo_t *cr,
 static gboolean
 swfdec_movie_mouse_events (SwfdecMovie *movie)
 {
-  return TRUE;
+  SwfdecAsObject *object;
+
+  /* root movies don't get event */
+  if (movie->parent == NULL)
+    return FALSE;
+  /* look if we have a script that gets events */
+  if (movie->events && swfdec_event_list_has_mouse_events (movie->events))
+    return TRUE;
+  /* otherwise, require at least one of the custom script handlers */
+  object = SWFDEC_AS_OBJECT (movie);
+  if (swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onRollOver) ||
+      swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onRollOut) ||
+      swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onDragOver) ||
+      swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onDragOut) ||
+      swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onPress) ||
+      swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onRelease) ||
+      swfdec_as_object_has_variable (object, SWFDEC_AS_STR_onReleaseOutside))
+    return TRUE;
+  return FALSE;
 }
 
 static void
commit d69d12362398e0f61d8a34577fd48d5f17dd19c1
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 16:25:59 2007 +0100

    confused mouse_in and mouse_out vfuncs

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 6ed95ec..0fe6f66 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1040,13 +1040,13 @@ swfdec_player_grab_mouse_movie (SwfdecPlayer *player)
       if (below_mouse == player->mouse_grab &&
 	  player->mouse_below != player->mouse_grab) {
 	SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
-	if (klass->mouse_out)
-	  klass->mouse_out (player->mouse_grab);
+	if (klass->mouse_in)
+	  klass->mouse_in (player->mouse_grab);
       } else if (below_mouse != player->mouse_grab &&
 	  player->mouse_below == player->mouse_grab) {
 	SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
-	if (klass->mouse_in)
-	  klass->mouse_in (player->mouse_grab);
+	if (klass->mouse_out)
+	  klass->mouse_out (player->mouse_grab);
       }
     }
   } else {
commit f3193d1c9d4b5a4729a4d89ceff0f81142368014
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 16:22:00 2007 +0100

    number buttons correctly and release the mouse grab on button release

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index b3e63dd..6ed95ec 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1129,6 +1129,8 @@ swfdec_player_do_mouse_release (SwfdecPlayer *player, guint button)
     SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
     if (klass->mouse_release)
       klass->mouse_release (player->mouse_grab, button);
+    if (button == 0)
+      player->mouse_grab = player->mouse_below;
   }
 
   /* FIXME: allow events to pass through */
@@ -1193,9 +1195,9 @@ swfdec_player_do_handle_mouse (SwfdecPlayer *player,
   SWFDEC_LOG ("handling mouse for %g %g %d", x, y, button);
   ret = swfdec_player_do_mouse_move (player, x, y);
   if (button > 0) {
-    ret |= swfdec_player_do_mouse_press (player, button);
+    ret |= swfdec_player_do_mouse_press (player, button - 1);
   } else if (button < 0) {
-    ret |= swfdec_player_do_mouse_release (player, -button);
+    ret |= swfdec_player_do_mouse_release (player, -button - 1);
   }
   swfdec_player_perform_actions (player);
   swfdec_player_unlock (player);
commit 204b5399601786c413e9b5a57393b274716f97ba
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 16:21:28 2007 +0100

    only react to mouse button 0

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 963ef4e..620a42b 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -1297,14 +1297,20 @@ swfdec_movie_mouse_out (SwfdecMovie *movie)
 static void
 swfdec_movie_mouse_press (SwfdecMovie *movie, guint button)
 {
+  if (button != 0)
+    return;
   swfdec_movie_queue_script (movie, SWFDEC_EVENT_PRESS);
 }
 
 static void
 swfdec_movie_mouse_release (SwfdecMovie *movie, guint button)
 {
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  SwfdecPlayer *player;
+  
+  if (button != 0)
+    return;
 
+  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
   if (player->mouse_below == movie)
     swfdec_movie_queue_script (movie, SWFDEC_EVENT_RELEASE);
   else
commit 7883a7be77cf576087f21730452b0858eaeb2eb7
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 16:13:57 2007 +0100

    fix _contains() checks
    
    lots of stupid bugfixes:
    - return the actual child movie if it was relevant
    - include drawn stuff in the computations
    - NULL the movie if it does not care about events

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index dfdf64d..963ef4e 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -670,7 +670,7 @@ swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y, gboolean even
   klass = SWFDEC_MOVIE_GET_CLASS (movie);
   g_return_val_if_fail (klass->contains, NULL);
   ret = klass->contains (movie, x, y, events);
-  if (events && ret && swfdec_movie_get_mouse_events (ret))
+  if (events && ret && !swfdec_movie_get_mouse_events (ret))
     ret = NULL;
 
   return ret;
@@ -680,8 +680,10 @@ static SwfdecMovie *
 swfdec_movie_do_contains (SwfdecMovie *movie, double x, double y, gboolean events)
 {
   GList *walk;
+  GSList *walk2;
   SwfdecMovie *ret, *got;
 
+  ret = NULL;
   for (walk = movie->list; walk; walk = walk->next) {
     SwfdecMovie *child = walk->data;
     
@@ -714,6 +716,16 @@ swfdec_movie_do_contains (SwfdecMovie *movie, double x, double y, gboolean event
       }
     }
   }
+  if (ret)
+    return ret;
+
+  for (walk2 = movie->draws; walk2; walk2 = walk2->next) {
+    SwfdecDraw *draw = walk2->data;
+
+    if (swfdec_draw_contains (draw, x, y))
+      return movie;
+  }
+
   return NULL;
 }
 
commit da051f0e1fb308fc4389a9088762de915d9b0e24
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 15:33:14 2007 +0100

    set default event handlers for SwfdecMovie mouse events

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 3723dc7..dfdf64d 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -1261,32 +1261,48 @@ swfdec_movie_do_render (SwfdecMovie *movie, cairo_t *cr,
 static gboolean
 swfdec_movie_mouse_events (SwfdecMovie *movie)
 {
-  return FALSE;
+  return TRUE;
 }
 
 static void
 swfdec_movie_mouse_in (SwfdecMovie *movie)
 {
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)))
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_DRAG_OVER);
+  else
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OVER);
 }
 
 static void
 swfdec_movie_mouse_out (SwfdecMovie *movie)
 {
+  if (swfdec_player_is_mouse_pressed (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)))
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_DRAG_OUT);
+  else
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_ROLL_OUT);
 }
 
 static void
 swfdec_movie_mouse_press (SwfdecMovie *movie, guint button)
 {
+  swfdec_movie_queue_script (movie, SWFDEC_EVENT_PRESS);
 }
 
 static void
 swfdec_movie_mouse_release (SwfdecMovie *movie, guint button)
 {
+  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+
+  if (player->mouse_below == movie)
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_RELEASE);
+  else
+    swfdec_movie_queue_script (movie, SWFDEC_EVENT_RELEASE_OUTSIDE);
 }
 
 static void
 swfdec_movie_mouse_move (SwfdecMovie *movie, double x, double y)
 {
+  /* nothing to do here, it's just there so we don't need to check for NULL */
 }
 
 static void
commit 123db9dd53b5bb2c17738e3572a9c33c2a9e4396
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 15:32:54 2007 +0100

    add swfdec_player_is_mouse_pressed() macro for code clarity

diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index fd6e2cf..b3e63dd 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1034,7 +1034,7 @@ swfdec_player_grab_mouse_movie (SwfdecPlayer *player)
       below_mouse = NULL;
     }
   }
-  if (player->mouse_button & 1) {
+  if (swfdec_player_is_mouse_pressed (player)) {
     /* a mouse grab is active */
     if (player->mouse_grab) {
       if (below_mouse == player->mouse_grab &&
@@ -2207,7 +2207,7 @@ swfdec_player_mouse_press (SwfdecPlayer *player, double x, double y,
   g_return_val_if_fail (SWFDEC_IS_PLAYER (player), FALSE);
   g_return_val_if_fail (button > 0 && button <= 32, FALSE);
 
-  g_signal_emit (player, signals[HANDLE_MOUSE], 0, x, y, 0, &ret);
+  g_signal_emit (player, signals[HANDLE_MOUSE], 0, x, y, button, &ret);
 
   return ret;
 }
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index 50230db..8fff190 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -174,6 +174,7 @@ void		swfdec_player_set_export_class	(SwfdecPlayer *		player,
 						 const char *		name,
 						 SwfdecAsObject *	object);
 
+#define swfdec_player_is_mouse_pressed(player) ((player)->mouse_button & 1)
 void		swfdec_player_invalidate	(SwfdecPlayer *		player,
 						 const SwfdecRect *	rect);
 void		swfdec_player_add_timeout	(SwfdecPlayer *		player,
commit d3fd07498dcebbbea0b6edcabd929e1ab218f1ad
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 15:18:10 2007 +0100

    add swfdec_as_object_has_variable()

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index a2d4842..5ecfa1d 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -932,6 +932,36 @@ swfdec_as_object_get_variable_and_flags (SwfdecAsObject *object,
 }
 
 /**
+ * swfdec_as_object_has_variable:
+ * @object: a #SwfdecAsObject
+ * @variable: garbage-collected variable name
+ *
+ * Checks if a user-set @variable with the given name exists on @object. This 
+ * function does not check variables that are available via an overwritten get 
+ * function of the object's class.
+ *
+ * Returns: %TRUE if the @object contains the given @variable
+ **/
+gboolean
+swfdec_as_object_has_variable (SwfdecAsObject *object, const char *variable)
+{
+  guint i;
+  SwfdecAsVariable *var;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), FALSE);
+  
+  for (i = 0; i <= SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT && object != NULL; i++) {
+    var = swfdec_as_object_hash_lookup (object, variable);
+    if (var) {
+      /* FIXME: propflags? */
+      return TRUE;
+    }
+    object = swfdec_as_object_get_prototype_internal (object);
+  }
+  return FALSE;
+}
+
+/**
  * swfdec_as_object_delete_variable:
  * @object: a #SwfdecAsObject
  * @variable: garbage-collected name of the variable
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index 5c76b3a..f32723d 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -143,6 +143,8 @@ gboolean	swfdec_as_object_get_variable_and_flags
 						 SwfdecAsValue *	value,
 						 guint *		flags,
 						 SwfdecAsObject **	pobject);
+gboolean	swfdec_as_object_has_variable	(SwfdecAsObject *	object,
+						 const char *		variable);
 SwfdecAsDeleteReturn
 		swfdec_as_object_delete_variable(SwfdecAsObject *	object,
 						 const char *		variable);
commit 17ec867f969ad58e64cd5c7aec6b18ba04e112d5
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 15:17:58 2007 +0100

    check event receiving by calling a Movie vfunc
    
    also add stubs for all event handlers to SwfdecMovie

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 3cbc0d0..3723dc7 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -618,6 +618,28 @@ swfdec_movie_get_mouse (SwfdecMovie *movie, double *x, double *y)
 }
 
 /**
+ * swfdec_movie_get_mouse_events:
+ * @movie: a #SwfdecMovie
+ *
+ * Checks if this movie should respond to mouse events.
+ *
+ * Returns: %TRUE if this movie can receive mouse events
+ **/
+gboolean
+swfdec_movie_get_mouse_events (SwfdecMovie *movie)
+{
+  SwfdecMovieClass *klass;
+
+  g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), FALSE);
+
+  klass = SWFDEC_MOVIE_GET_CLASS (movie);
+  if (klass->mouse_events)
+    return klass->mouse_events (movie);
+  else
+    return FALSE;
+}
+
+/**
  * swfdec_movie_get_movie_at:
  * @movie: a #SwfdecMovie
  * @x: x coordinate in parent's coordinate space
@@ -648,7 +670,7 @@ swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y, gboolean even
   klass = SWFDEC_MOVIE_GET_CLASS (movie);
   g_return_val_if_fail (klass->contains, NULL);
   ret = klass->contains (movie, x, y, events);
-  if (events && ret && !ret->receive_events)
+  if (events && ret && swfdec_movie_get_mouse_events (ret))
     ret = NULL;
 
   return ret;
@@ -671,7 +693,7 @@ swfdec_movie_do_contains (SwfdecMovie *movie, double x, double y, gboolean event
     if (got != NULL) {
       if (events) {
 	/* set the return value to the topmost movie */
-	if (got->receive_events) {
+	if (swfdec_movie_get_mouse_events (got)) {
 	  ret = got;
 	} else if (ret == NULL) {
 	  ret = movie;
@@ -1236,6 +1258,37 @@ swfdec_movie_do_render (SwfdecMovie *movie, cairo_t *cr,
   g_assert (clips == NULL);
 }
 
+static gboolean
+swfdec_movie_mouse_events (SwfdecMovie *movie)
+{
+  return FALSE;
+}
+
+static void
+swfdec_movie_mouse_in (SwfdecMovie *movie)
+{
+}
+
+static void
+swfdec_movie_mouse_out (SwfdecMovie *movie)
+{
+}
+
+static void
+swfdec_movie_mouse_press (SwfdecMovie *movie, guint button)
+{
+}
+
+static void
+swfdec_movie_mouse_release (SwfdecMovie *movie, guint button)
+{
+}
+
+static void
+swfdec_movie_mouse_move (SwfdecMovie *movie, double x, double y)
+{
+}
+
 static void
 swfdec_movie_class_init (SwfdecMovieClass * movie_class)
 {
@@ -1258,6 +1311,12 @@ swfdec_movie_class_init (SwfdecMovieClass * movie_class)
   movie_class->render = swfdec_movie_do_render;
   movie_class->contains = swfdec_movie_do_contains;
   movie_class->iterate_end = swfdec_movie_iterate_end;
+  movie_class->mouse_events = swfdec_movie_mouse_events;
+  movie_class->mouse_in = swfdec_movie_mouse_in;
+  movie_class->mouse_out = swfdec_movie_mouse_out;
+  movie_class->mouse_press = swfdec_movie_mouse_press;
+  movie_class->mouse_release = swfdec_movie_mouse_release;
+  movie_class->mouse_move = swfdec_movie_mouse_move;
 }
 
 void
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 56c3038..678a0da 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -158,8 +158,6 @@ struct _SwfdecMovie {
   int			draw_x;			/* current x position for drawing */
   int			draw_y;			/* current y position for drawing */
 
-  /* event handling */
-  guint			receive_events;	      	/* "refcount", >0 to receive events */
   /* leftover unimplemented variables from the Actionscript spec */
 #if 0
   int droptarget;
@@ -187,6 +185,7 @@ struct _SwfdecMovieClass {
 						 double			y,
 						 gboolean		events);
   /* mouse handling */
+  gboolean		(* mouse_events)	(SwfdecMovie *		movie);
   void			(* mouse_in)      	(SwfdecMovie *		movie);
   void			(* mouse_out)      	(SwfdecMovie *		movie);
   void			(* mouse_press)      	(SwfdecMovie *		movie,
@@ -269,6 +268,7 @@ void		swfdec_movie_set_depth		(SwfdecMovie *		movie,
 void		swfdec_movie_get_mouse		(SwfdecMovie *		movie,
 						 double *		x,
 						 double *		y);
+gboolean	swfdec_movie_get_mouse_events	(SwfdecMovie *		movie);
 #define swfdec_movie_contains(movie, x, y) \
   (swfdec_movie_get_movie_at ((movie), (x), (y), FALSE) != NULL)
 SwfdecMovie *	swfdec_movie_get_movie_at	(SwfdecMovie *		movie,
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 8564063..fd6e2cf 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1029,7 +1029,7 @@ swfdec_player_grab_mouse_movie (SwfdecPlayer *player)
   for (walk = g_list_last (player->roots); walk; walk = walk->prev) {
     below_mouse = swfdec_movie_get_movie_at (walk->data, x, y, TRUE);
     if (below_mouse) {
-      if (below_mouse->receive_events == TRUE)
+      if (swfdec_movie_get_mouse_events (below_mouse))
 	break;
       below_mouse = NULL;
     }
commit 47c22d78488f897cb825c60f7aa21036d0edeec6
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 12:59:06 2007 +0100

    typo

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 8414e6a..a2d4842 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -939,7 +939,7 @@ swfdec_as_object_get_variable_and_flags (SwfdecAsObject *object,
  * Deletes the given variable if possible. If the variable is protected from 
  * deletion, it will not be deleted.
  *
- * Returns: See #SwfdecAsDeleteReutnr for details of the return value.
+ * Returns: See #SwfdecAsDeleteReturn for details of the return value.
  **/
 SwfdecAsDeleteReturn
 swfdec_as_object_delete_variable (SwfdecAsObject *object, const char *variable)
commit 640bbb2c826d00da3cc7839f3ae51378957e14c4
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 12:42:27 2007 +0100

    don't segfault if we don't have a movie

diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 83cf5b2..3cbc0d0 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -648,7 +648,7 @@ swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y, gboolean even
   klass = SWFDEC_MOVIE_GET_CLASS (movie);
   g_return_val_if_fail (klass->contains, NULL);
   ret = klass->contains (movie, x, y, events);
-  if (events && !ret->receive_events)
+  if (events && ret && !ret->receive_events)
     ret = NULL;
 
   return ret;
commit e24b12a9598ca54dd05d4a53e0d96366c1edf489
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 12:35:55 2007 +0100

    only handle single clicks
    
    double and triple clicks shouldn't cause a click event

diff --git a/libswfdec-gtk/swfdec_gtk_widget.c b/libswfdec-gtk/swfdec_gtk_widget.c
index 14a0174..4836aa0 100644
--- a/libswfdec-gtk/swfdec_gtk_widget.c
+++ b/libswfdec-gtk/swfdec_gtk_widget.c
@@ -102,7 +102,7 @@ swfdec_gtk_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
   SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
   SwfdecGtkWidgetPrivate *priv = widget->priv;
 
-  if (event->button <= 32 && priv->interactive && priv->player) {
+  if (event->type == GDK_BUTTON_PRESS && event->button <= 32 && priv->interactive && priv->player) {
     swfdec_player_mouse_press (priv->player, event->x, event->y, event->button);
   }
   return FALSE;
commit dc959b9439aa0e440efea2ed9e62da964ea418bc
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 12:34:52 2007 +0100

    port widget to new API

diff --git a/libswfdec-gtk/swfdec_gtk_widget.c b/libswfdec-gtk/swfdec_gtk_widget.c
index eb92313..14a0174 100644
--- a/libswfdec-gtk/swfdec_gtk_widget.c
+++ b/libswfdec-gtk/swfdec_gtk_widget.c
@@ -33,8 +33,6 @@ struct _SwfdecGtkWidgetPrivate
   gboolean		renderer_set;	/* TRUE if a special renderer has been set */
   cairo_surface_type_t	renderer;	/* the renderer that was set */
   gboolean		interactive;	/* TRUE if this widget propagates keyboard and mouse events */
-
-  int			button;		/* status of mouse button in displayed movie */
 };
 
 enum {
@@ -81,7 +79,7 @@ swfdec_gtk_widget_motion_notify (GtkWidget *gtkwidget, GdkEventMotion *event)
   gdk_window_get_pointer (gtkwidget->window, &x, &y, NULL);
 
   if (priv->interactive && priv->player)
-    swfdec_player_handle_mouse (priv->player, x, y, priv->button);
+    swfdec_player_mouse_move (priv->player, x, y);
   
   return FALSE;
 }
@@ -93,8 +91,7 @@ swfdec_gtk_widget_leave_notify (GtkWidget *gtkwidget, GdkEventCrossing *event)
   SwfdecGtkWidgetPrivate *priv = widget->priv;
 
   if (priv->interactive && priv->player) {
-    priv->button = 0;
-    swfdec_player_handle_mouse (priv->player, event->x, event->y, 0);
+    swfdec_player_mouse_move (priv->player, event->x, event->y);
   }
   return FALSE;
 }
@@ -105,10 +102,8 @@ swfdec_gtk_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
   SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
   SwfdecGtkWidgetPrivate *priv = widget->priv;
 
-  if (event->button == 1) {
-    priv->button = 1;
-    if (priv->interactive && priv->player)
-      swfdec_player_handle_mouse (priv->player, event->x, event->y, 1);
+  if (event->button <= 32 && priv->interactive && priv->player) {
+    swfdec_player_mouse_press (priv->player, event->x, event->y, event->button);
   }
   return FALSE;
 }
@@ -119,10 +114,8 @@ swfdec_gtk_widget_button_release (GtkWidget *gtkwidget, GdkEventButton *event)
   SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
   SwfdecGtkWidgetPrivate *priv = widget->priv;
 
-  if (event->button == 1) {
-    priv->button = 0;
-    if (priv->interactive && priv->player)
-      swfdec_player_handle_mouse (priv->player, event->x, event->y, 0);
+  if (event->button <= 32 && priv->interactive && priv->player) {
+    swfdec_player_mouse_release (priv->player, event->x, event->y, event->button);
   }
   return FALSE;
 }
commit 59b864c81048bc6bc0f0af1c8ce0b0de51b9f148
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 22 11:37:08 2007 +0100

    first steps at redoing mouse input.
    
    This introduces the new mouse handling vfuncs and uses them.

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 8a18ef5..cb94b6a 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -208,7 +208,7 @@ swfdec_button_movie_init_movie (SwfdecMovie *mov)
   swfdec_button_movie_change_state (movie, SWFDEC_BUTTON_UP);
 }
 
-static gboolean
+static gboolean G_GNUC_UNUSED
 swfdec_button_movie_mouse_in (SwfdecMovie *movie, double x, double y)
 {
   GList *walk;
@@ -252,7 +252,7 @@ swfdec_button_movie_get_state (SwfdecButtonMovie *movie, gboolean mouse_in, int
   }
 }
 
-static void
+static void G_GNUC_UNUSED
 swfdec_button_movie_mouse_change (SwfdecMovie *mov, double x, double y, 
     gboolean mouse_in, int button)
 {
@@ -272,8 +272,8 @@ swfdec_button_movie_class_init (SwfdecButtonMovieClass * g_class)
 
   movie_class->init_movie = swfdec_button_movie_init_movie;
   movie_class->update_extents = swfdec_button_movie_update_extents;
-  movie_class->mouse_in = swfdec_button_movie_mouse_in;
-  movie_class->mouse_change = swfdec_button_movie_mouse_change;
+  //movie_class->mouse_in = swfdec_button_movie_mouse_in;
+  //movie_class->mouse_change = swfdec_button_movie_mouse_change;
 }
 
 static void
diff --git a/libswfdec/swfdec_graphic_movie.c b/libswfdec/swfdec_graphic_movie.c
index a1e86af..ce9e67d 100644
--- a/libswfdec/swfdec_graphic_movie.c
+++ b/libswfdec/swfdec_graphic_movie.c
@@ -49,10 +49,14 @@ swfdec_graphic_movie_render (SwfdecMovie *movie, cairo_t *cr,
   swfdec_graphic_render (movie->graphic, cr, trans, inval);
 }
 
-static gboolean
-swfdec_graphic_movie_mouse_in (SwfdecMovie *movie, double x, double y)
+static SwfdecMovie *
+swfdec_graphic_movie_contains (SwfdecMovie *movie, double x, double y, 
+    gboolean events)
 {
-  return swfdec_graphic_mouse_in (movie->graphic, x, y);
+  if (swfdec_graphic_mouse_in (movie->graphic, x, y))
+    return movie;
+  else
+    return NULL;
 }
 
 static void
@@ -87,7 +91,7 @@ swfdec_graphic_movie_class_init (SwfdecGraphicMovieClass * g_class)
   movie_class->update_extents = swfdec_graphic_movie_update_extents;
   movie_class->replace = swfdec_graphic_movie_replace;
   movie_class->render = swfdec_graphic_movie_render;
-  movie_class->mouse_in = swfdec_graphic_movie_mouse_in;
+  movie_class->contains = swfdec_graphic_movie_contains;
 }
 
 static void
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 1e1e841..83cf5b2 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -496,30 +496,6 @@ swfdec_movie_queue_script (SwfdecMovie *movie, SwfdecEventType condition)
   swfdec_player_add_action (player, movie, condition, importance);
 }
 
-/* NB: coordinates are in movie's coordiante system. Use swfdec_movie_get_mouse
- * if you have global coordinates */
-gboolean
-swfdec_movie_mouse_in (SwfdecMovie *movie, double x, double y)
-{
-  SwfdecMovieClass *klass;
-  GList *walk;
-
-  klass = SWFDEC_MOVIE_GET_CLASS (movie);
-  if (klass->mouse_in != NULL &&
-      klass->mouse_in (movie, x, y))
-    return TRUE;
-
-  for (walk = movie->list; walk; walk = walk->next) {
-    double tmp_x = x;
-    double tmp_y = y;
-    SwfdecMovie *cur = walk->data;
-    cairo_matrix_transform_point (&cur->inverse_matrix, &tmp_x, &tmp_y);
-    if (swfdec_movie_mouse_in (cur, tmp_x, tmp_y))
-      return TRUE;
-  }
-  return FALSE;
-}
-
 void
 swfdec_movie_local_to_global (SwfdecMovie *movie, double *x, double *y)
 {
@@ -641,97 +617,80 @@ swfdec_movie_get_mouse (SwfdecMovie *movie, double *x, double *y)
   swfdec_movie_global_to_local (movie, x, y);
 }
 
-void
-swfdec_movie_send_mouse_change (SwfdecMovie *movie, gboolean release)
-{
-  double x, y;
-  gboolean mouse_in;
-  int button;
-  SwfdecMovieClass *klass;
-
-  swfdec_movie_get_mouse (movie, &x, &y);
-  if (release) {
-    mouse_in = FALSE;
-    button = 0;
-  } else {
-    mouse_in = swfdec_movie_mouse_in (movie, x, y);
-    button = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->mouse_button;
-  }
-  klass = SWFDEC_MOVIE_GET_CLASS (movie);
-  g_assert (klass->mouse_change != NULL);
-  klass->mouse_change (movie, x, y, mouse_in, button);
-}
-
 /**
  * swfdec_movie_get_movie_at:
  * @movie: a #SwfdecMovie
  * @x: x coordinate in parent's coordinate space
  * @y: y coordinate in the parent's coordinate space
+ * @events: %TRUE to only respect movies that receive events
  *
  * Gets the child at the given coordinates. The coordinates are in the 
  * coordinate system of @movie's parent (or the global coordinate system for
- * root movies).
+ * root movies). The @events parameter determines if movies that don't receive
+ * events should be respected.
  *
  * Returns: the child of @movie at the given coordinates or %NULL if none
  **/
 SwfdecMovie *
-swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y)
+swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y, gboolean events)
 {
-  GList *walk, *clip_walk;
-  int clip_depth = 0;
   SwfdecMovie *ret;
   SwfdecMovieClass *klass;
 
+  g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), NULL);
+
   SWFDEC_LOG ("%s %p getting mouse at: %g %g", G_OBJECT_TYPE_NAME (movie), movie, x, y);
   if (!swfdec_rect_contains (&movie->extents, x, y)) {
     return NULL;
   }
   cairo_matrix_transform_point (&movie->inverse_matrix, &x, &y);
 
-  /* first check if the movie can handle mouse events, and if it can,
-   * ignore its children.
-   * Dunno if that's correct */
   klass = SWFDEC_MOVIE_GET_CLASS (movie);
-  if (klass->mouse_change) {
-    if (swfdec_movie_mouse_in (movie, x, y))
-      return movie;
-    else
-      return NULL;
-  }
-  for (walk = clip_walk = g_list_last (movie->list); walk; walk = walk->prev) {
+  g_return_val_if_fail (klass->contains, NULL);
+  ret = klass->contains (movie, x, y, events);
+  if (events && !ret->receive_events)
+    ret = NULL;
+
+  return ret;
+}
+
+static SwfdecMovie *
+swfdec_movie_do_contains (SwfdecMovie *movie, double x, double y, gboolean events)
+{
+  GList *walk;
+  SwfdecMovie *ret, *got;
+
+  for (walk = movie->list; walk; walk = walk->next) {
     SwfdecMovie *child = walk->data;
-    if (walk == clip_walk) {
-      clip_depth = 0;
-      for (clip_walk = clip_walk->prev; clip_walk; clip_walk = clip_walk->prev) {
-	SwfdecMovie *clip = walk->data;
-	if (clip->clip_depth) {
-	  double tmpx = x, tmpy = y;
-	  cairo_matrix_transform_point (&clip->inverse_matrix, &tmpx, &tmpy);
-	  if (!swfdec_movie_mouse_in (clip, tmpx, tmpy)) {
-	    SWFDEC_LOG ("skipping depth %d to %d due to clipping", clip->depth, clip->clip_depth);
-	    clip_depth = child->clip_depth;
-	  }
-	  break;
-	}
-      }
-    }
-    if (child->clip_depth) {
-      SWFDEC_LOG ("resetting clip depth");
-      clip_depth = 0;
-      continue;
-    }
-    if (child->depth <= clip_depth && clip_depth) {
-      SWFDEC_DEBUG ("ignoring depth=%d, it's clipped (clip_depth %d)", child->depth, clip_depth);
-      continue;
-    }
+    
     if (!child->visible) {
-      SWFDEC_LOG ("child %s %s (depth %d) is invisible, ignoring", G_OBJECT_TYPE_NAME (movie), movie->name, movie->depth);
+      SWFDEC_LOG ("%s %s (depth %d) is invisible, ignoring", G_OBJECT_TYPE_NAME (movie), movie->name, movie->depth);
       continue;
     }
-
-    ret = swfdec_movie_get_movie_at (child, x, y);
-    if (ret)
-      return ret;
+    got = swfdec_movie_get_movie_at (child, x, y, events);
+    if (got != NULL) {
+      if (events) {
+	/* set the return value to the topmost movie */
+	if (got->receive_events) {
+	  ret = got;
+	} else if (ret == NULL) {
+	  ret = movie;
+	}
+      } else {
+	/* if thie is not a clipped movie, we've found something */
+	if (child->clip_depth == 0)
+	  return movie;
+      }
+    } else {
+      if (child->clip_depth) {
+	/* skip obscured movies */
+	SwfdecMovie *tmp = walk->next ? walk->next->data : NULL;
+	while (tmp && tmp->depth <= child->clip_depth) {
+	  walk = walk->next;
+	  tmp = walk->next ? walk->next->data : NULL;
+	}
+      }
+    }
   }
   return NULL;
 }
@@ -1297,6 +1256,7 @@ swfdec_movie_class_init (SwfdecMovieClass * movie_class)
 	  G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
   movie_class->render = swfdec_movie_do_render;
+  movie_class->contains = swfdec_movie_do_contains;
   movie_class->iterate_end = swfdec_movie_iterate_end;
 }
 
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 183e022..56c3038 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -158,6 +158,8 @@ struct _SwfdecMovie {
   int			draw_x;			/* current x position for drawing */
   int			draw_y;			/* current y position for drawing */
 
+  /* event handling */
+  guint			receive_events;	      	/* "refcount", >0 to receive events */
   /* leftover unimplemented variables from the Actionscript spec */
 #if 0
   int droptarget;
@@ -180,15 +182,31 @@ struct _SwfdecMovieClass {
 						 const SwfdecColorTransform *trans,
 						 const SwfdecRect *	inval);
 
+  SwfdecMovie *		(* contains)		(SwfdecMovie *		movie,
+						 double			x,
+						 double			y,
+						 gboolean		events);
   /* mouse handling */
-  gboolean		(* mouse_in)		(SwfdecMovie *		movie,
+  void			(* mouse_in)      	(SwfdecMovie *		movie);
+  void			(* mouse_out)      	(SwfdecMovie *		movie);
+  void			(* mouse_press)      	(SwfdecMovie *		movie,
+						 guint			button);
+  void			(* mouse_release)      	(SwfdecMovie *		movie,
+						 guint			button);
+  void			(* mouse_move)      	(SwfdecMovie *		movie,
 						 double			x,
 						 double			y);
-  void			(* mouse_change)      	(SwfdecMovie *		movie,
-						 double			x,
-						 double			y,
-						 gboolean		mouse_in,
-						 int			button);
+  /* keyboard handling */
+  void			(* focus_in)		(SwfdecMovie *		movie,
+						 SwfdecMovie *		previous);
+  void			(* focus_out)		(SwfdecMovie *		movie,
+						 SwfdecMovie *		next);
+  void			(* key_pressed)		(SwfdecMovie *		movie,
+						 guint			keycode,
+						 guint			character);
+  void			(* key_released)      	(SwfdecMovie *		movie,
+						 guint			keycode,
+						 guint			character);
 
   /* iterating */
   void			(* iterate_start)     	(SwfdecMovie *		movie);
@@ -247,17 +265,16 @@ void		swfdec_movie_rect_global_to_local (SwfdecMovie *	movie,
 						 SwfdecRect *		rect);
 void		swfdec_movie_set_depth		(SwfdecMovie *		movie,
 						 int			depth);
+
 void		swfdec_movie_get_mouse		(SwfdecMovie *		movie,
 						 double *		x,
 						 double *		y);
-void		swfdec_movie_send_mouse_change	(SwfdecMovie *		movie,
-						 gboolean		release);
-gboolean	swfdec_movie_mouse_in		(SwfdecMovie *		movie,
-						 double			x,
-						 double			y);
+#define swfdec_movie_contains(movie, x, y) \
+  (swfdec_movie_get_movie_at ((movie), (x), (y), FALSE) != NULL)
 SwfdecMovie *	swfdec_movie_get_movie_at	(SwfdecMovie *		movie,
 						 double			x,
-						 double			y);
+						 double			y,
+						 gboolean		events);
 char *		swfdec_movie_get_path		(SwfdecMovie *		movie,
 						 gboolean		dot);
 void		swfdec_movie_render		(SwfdecMovie *		movie,
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 129b4fe..8564063 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -1017,68 +1017,122 @@ swfdec_player_set_drag_movie (SwfdecPlayer *player, SwfdecMovie *drag, gboolean
 }
 
 static void
-swfdec_player_update_mouse_position (SwfdecPlayer *player)
+swfdec_player_grab_mouse_movie (SwfdecPlayer *player)
 {
   GList *walk;
-  SwfdecMovie *mouse_grab = NULL;
+  double x, y;
+  SwfdecMovie *below_mouse = NULL;
 
-  if (player->mouse_button) {
-    mouse_grab = player->mouse_grab;
-  } else {
-    double x, y;
-    /* if the mouse button is pressed the grab widget stays the same (I think) */
-    x = player->mouse_x;
-    y = player->mouse_y;
-    swfdec_player_stage_to_global (player, &x, &y);
-    for (walk = g_list_last (player->roots); walk; walk = walk->prev) {
-      mouse_grab = swfdec_movie_get_movie_at (walk->data, x, y);
-      if (mouse_grab)
+  x = player->mouse_x;
+  y = player->mouse_y;
+  swfdec_player_stage_to_global (player, &x, &y);
+  for (walk = g_list_last (player->roots); walk; walk = walk->prev) {
+    below_mouse = swfdec_movie_get_movie_at (walk->data, x, y, TRUE);
+    if (below_mouse) {
+      if (below_mouse->receive_events == TRUE)
 	break;
+      below_mouse = NULL;
+    }
+  }
+  if (player->mouse_button & 1) {
+    /* a mouse grab is active */
+    if (player->mouse_grab) {
+      if (below_mouse == player->mouse_grab &&
+	  player->mouse_below != player->mouse_grab) {
+	SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
+	if (klass->mouse_out)
+	  klass->mouse_out (player->mouse_grab);
+      } else if (below_mouse != player->mouse_grab &&
+	  player->mouse_below == player->mouse_grab) {
+	SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
+	if (klass->mouse_in)
+	  klass->mouse_in (player->mouse_grab);
+      }
+    }
+  } else {
+    /* no mouse grab is active */
+    if (below_mouse != player->mouse_grab) {
+      if (player->mouse_grab) {
+	SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
+	if (klass->mouse_out)
+	  klass->mouse_out (player->mouse_grab);
+      }
+      if (below_mouse) {
+	SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (below_mouse);
+	if (klass->mouse_in)
+	  klass->mouse_in (below_mouse);
+      }
     }
+    player->mouse_grab = below_mouse;
   }
+  player->mouse_below = below_mouse;
   SWFDEC_DEBUG ("%s %p has mouse at %g %g", 
-      mouse_grab ? G_OBJECT_TYPE_NAME (mouse_grab) : "---", 
-      mouse_grab, player->mouse_x, player->mouse_y);
-  if (player->mouse_grab && mouse_grab != player->mouse_grab)
-    swfdec_movie_send_mouse_change (player->mouse_grab, TRUE);
-  player->mouse_grab = mouse_grab;
-  if (mouse_grab)
-    swfdec_movie_send_mouse_change (mouse_grab, FALSE);
+      player->mouse_grab ? G_OBJECT_TYPE_NAME (player->mouse_grab) : "---", 
+      player->mouse_grab, player->mouse_x, player->mouse_y);
 }
 
-static void
-swfdec_player_do_mouse_move (SwfdecPlayer *player)
+static gboolean
+swfdec_player_do_mouse_move (SwfdecPlayer *player, double x, double y)
 {
   GList *walk;
-
+  
+  if (player->mouse_x != x || player->mouse_y != y) {
+    player->mouse_x = x;
+    player->mouse_y = y;
+    for (walk = player->movies; walk; walk = walk->next) {
+      swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_MOVE);
+    }
+    swfdec_player_broadcast (player, SWFDEC_AS_STR_Mouse, SWFDEC_AS_STR_onMouseMove);
+  }
+  swfdec_player_grab_mouse_movie (player);
   swfdec_player_update_drag_movie (player);
-  for (walk = player->movies; walk; walk = walk->next) {
-    swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_MOVE);
+
+  /* FIXME: allow events to pass through */
+  return TRUE;
+}
+
+static gboolean
+swfdec_player_do_mouse_press (SwfdecPlayer *player, guint button)
+{
+  GList *walk;
+
+  player->mouse_button |= 1 << button;
+  if (button == 0) {
+    for (walk = player->movies; walk; walk = walk->next) {
+      swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_DOWN);
+    }
+    swfdec_player_broadcast (player, SWFDEC_AS_STR_Mouse, SWFDEC_AS_STR_onMouseDown);
+  }
+  if (player->mouse_grab) {
+    SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
+    if (klass->mouse_press)
+      klass->mouse_press (player->mouse_grab, button);
   }
-  swfdec_player_broadcast (player, SWFDEC_AS_STR_Mouse, SWFDEC_AS_STR_onMouseMove);
-  swfdec_player_update_mouse_position (player);
+
+  /* FIXME: allow events to pass through */
+  return TRUE;
 }
 
-static void
-swfdec_player_do_mouse_button (SwfdecPlayer *player)
+static gboolean
+swfdec_player_do_mouse_release (SwfdecPlayer *player, guint button)
 {
   GList *walk;
-  guint event;
-  const char *event_name;
 
-  if (player->mouse_button) {
-    event = SWFDEC_EVENT_MOUSE_DOWN;
-    event_name = SWFDEC_AS_STR_onMouseDown;
-  } else {
-    event = SWFDEC_EVENT_MOUSE_UP;
-    event_name = SWFDEC_AS_STR_onMouseUp;
+  player->mouse_button &= ~(1 << button);
+  if (button == 0) {
+    for (walk = player->movies; walk; walk = walk->next) {
+      swfdec_movie_queue_script (walk->data, SWFDEC_EVENT_MOUSE_UP);
+    }
+    swfdec_player_broadcast (player, SWFDEC_AS_STR_Mouse, SWFDEC_AS_STR_onMouseUp);
   }
-  for (walk = player->movies; walk; walk = walk->next) {
-    swfdec_movie_queue_script (walk->data, event);
+  if (player->mouse_grab) {
+    SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (player->mouse_grab);
+    if (klass->mouse_release)
+      klass->mouse_release (player->mouse_grab, button);
   }
-  swfdec_player_broadcast (player, SWFDEC_AS_STR_Mouse, event_name);
-  if (player->mouse_grab)
-    swfdec_movie_send_mouse_change (player->mouse_grab, FALSE);
+
+  /* FIXME: allow events to pass through */
+  return TRUE;
 }
 
 static void
@@ -1131,24 +1185,22 @@ static gboolean
 swfdec_player_do_handle_mouse (SwfdecPlayer *player, 
     double x, double y, int button)
 {
+  gboolean ret;
+
   if (!swfdec_player_lock (player))
     return FALSE;
 
-  SWFDEC_LOG ("handling mouse at %g %g %d", x, y, button);
-  if (player->mouse_x != x || player->mouse_y != y) {
-    player->mouse_x = x;
-    player->mouse_y = y;
-    swfdec_player_do_mouse_move (player);
-  }
-  if (player->mouse_button != button) {
-    player->mouse_button = button;
-    swfdec_player_do_mouse_button (player);
+  SWFDEC_LOG ("handling mouse for %g %g %d", x, y, button);
+  ret = swfdec_player_do_mouse_move (player, x, y);
+  if (button > 0) {
+    ret |= swfdec_player_do_mouse_press (player, button);
+  } else if (button < 0) {
+    ret |= swfdec_player_do_mouse_release (player, -button);
   }
   swfdec_player_perform_actions (player);
   swfdec_player_unlock (player);
 
-  /* FIXME: allow events to pass through */
-  return TRUE;
+  return ret;
 }
 
 void
@@ -1298,15 +1350,6 @@ swfdec_player_perform_actions (SwfdecPlayer *player)
   for (walk = player->roots; walk; walk = walk->next) {
     swfdec_movie_update (walk->data);
   }
-  /* update the state of the mouse when stuff below it moved */
-  if (swfdec_rectangle_contains_point (&player->invalid_extents, player->mouse_x, player->mouse_y)) {
-    SWFDEC_INFO ("=== NEED TO UPDATE mouse post-iteration ===");
-    swfdec_player_update_mouse_position (player);
-    while (swfdec_player_do_action (player));
-    for (walk = player->roots; walk; walk = walk->next) {
-      swfdec_movie_update (walk->data);
-    }
-  }
 }
 
 /* used for breakpoints */
@@ -1536,7 +1579,8 @@ swfdec_player_class_init (SwfdecPlayerClass *klass)
    * @player: the #SwfdecPlayer affected
    * @x: new x coordinate of the mouse
    * @y: new y coordinate of the mouse
-   * @button: 1 if the button is pressed, 0 if not
+   * @button: 0 for a mouse move, a positive number if a button was pressed,
+   *          a negative number if a button was released
    *
    * This signal is emitted whenever @player should respond to a mouse event. If
    * any of the handlers returns TRUE, swfdec_player_handle_mouse() will return 
@@ -2113,31 +2157,86 @@ swfdec_init (void)
 }
 
 /**
- * swfdec_player_handle_mouse:
+ * swfdec_player_mouse_move:
  * @player: a #SwfdecPlayer
  * @x: x coordinate of mouse
  * @y: y coordinate of mouse
- * @button: 1 for pressed, 0 for not pressed
  *
- * Updates the current mouse status. If the mouse has left the area of @player,
+ * Updates the current mouse position. If the mouse has left the area of @player,
  * you should pass values outside the movie size for @x and @y. You will 
  * probably want to call swfdec_player_advance() before to update the player to
  * the correct time when calling this function.
  *
- * Returns: %TRUE if the mouse event was handled. %FALSE to propagate the event
- *          further. A mouse event may not be handled if the user clicked on a 
- *          translucent area.
+ * Returns: %TRUE if the mouse event was handled. %FALSE if the event should be
+ *	    propagated further. A mouse event may not be handled if the user 
+ *	    clicked on a translucent area.
  **/
 gboolean
-swfdec_player_handle_mouse (SwfdecPlayer *player, 
-    double x, double y, int button)
+swfdec_player_mouse_move (SwfdecPlayer *player, double x, double y)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), FALSE);
+
+  g_signal_emit (player, signals[HANDLE_MOUSE], 0, x, y, 0, &ret);
+
+  return ret;
+}
+
+/**
+ * swfdec_player_mouse_press:
+ * @player: a #SwfdecPlayer
+ * @x: x coordinate of mouse
+ * @y: y coordinate of mouse
+ * @button: number of the button that was pressed. Swfdec supports up to 32
+ *          buttons.
+ *
+ * Tells the @player that the mouse button @button was pressed at the given
+ * coordinate.
+ *
+ * Returns: %TRUE if the mouse event was handled. %FALSE if the event should be
+ *	    propagated further. A mouse event may not be handled if the user 
+ *	    clicked on a translucent area.
+ **/
+gboolean
+swfdec_player_mouse_press (SwfdecPlayer *player, double x, double y, 
+    guint button)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), FALSE);
+  g_return_val_if_fail (button > 0 && button <= 32, FALSE);
+
+  g_signal_emit (player, signals[HANDLE_MOUSE], 0, x, y, 0, &ret);
+
+  return ret;
+}
+
+/**
+ * swfdec_player_mouse_release:
+ * @player: a #SwfdecPlayer
+ * @x: x coordinate of mouse
+ * @y: y coordinate of mouse
+ * @button: number of the button that was released. Swfdec supports up to 32
+ *          buttons.
+ *
+ * Tells the @player that the mouse button @button was released at the given
+ * coordinate.
+ *
+ * Returns: %TRUE if the mouse event was handled. %FALSE if the event should be
+ *	    propagated further. A mouse event may not be handled if the user 
+ *	    clicked on a translucent area.
+ **/
+gboolean
+swfdec_player_mouse_release (SwfdecPlayer *player, double x, double y, 
+    guint button)
 {
   gboolean ret;
 
   g_return_val_if_fail (SWFDEC_IS_PLAYER (player), FALSE);
-  g_return_val_if_fail (button == 0 || button == 1, FALSE);
+  g_return_val_if_fail (button > 0 && button <= 32, FALSE);
 
-  g_signal_emit (player, signals[HANDLE_MOUSE], 0, x, y, button, &ret);
+  g_signal_emit (player, signals[HANDLE_MOUSE], 0, x, y, -button, &ret);
 
   return ret;
 }
diff --git a/libswfdec/swfdec_player.h b/libswfdec/swfdec_player.h
index d28fce5..903eabb 100644
--- a/libswfdec/swfdec_player.h
+++ b/libswfdec/swfdec_player.h
@@ -113,10 +113,17 @@ void		swfdec_player_render		(SwfdecPlayer *	player,
 						 double		height);
 void		swfdec_player_advance		(SwfdecPlayer *	player,
 						 gulong		msecs);
-gboolean	swfdec_player_handle_mouse	(SwfdecPlayer *	player, 
+gboolean	swfdec_player_mouse_move	(SwfdecPlayer *	player, 
+						 double		x,
+						 double		y);
+gboolean	swfdec_player_mouse_press	(SwfdecPlayer *	player, 
+						 double		x,
+						 double		y,
+						 guint		button);
+gboolean	swfdec_player_mouse_release	(SwfdecPlayer *	player, 
 						 double		x,
 						 double		y,
-						 int		button);
+						 guint		button);
 gboolean	swfdec_player_key_press		(SwfdecPlayer *	player,
 						 guint		keycode,
 						 guint		character);
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index e5c14f7..50230db 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -99,7 +99,8 @@ struct _SwfdecPlayer
   SwfdecMouseCursor	mouse_cursor;		/* cursor that should be shown */
   double      		mouse_x;		/* in stage coordinates */
   double		mouse_y;		/* in stage coordinates */
-  int			mouse_button; 		/* 0 for not pressed, 1 for pressed */
+  guint			mouse_button; 		/* 0 for not pressed, 1 for pressed */
+  SwfdecMovie *		mouse_below;		/* movie that currently is below the mouse */
   SwfdecMovie *		mouse_grab;		/* movie that currently has the mouse */
   SwfdecMovie *		mouse_drag;		/* current movie activated by startDrag */
   gboolean		mouse_drag_center;	/* TRUE to use center of movie at mouse, FALSE for movie's (0,0) */
diff --git a/libswfdec/swfdec_sprite_movie_as.c b/libswfdec/swfdec_sprite_movie_as.c
index c9ef84a..9a0f045 100644
--- a/libswfdec/swfdec_sprite_movie_as.c
+++ b/libswfdec/swfdec_sprite_movie_as.c
@@ -499,7 +499,7 @@ swfdec_sprite_movie_hitTest (SwfdecAsContext *cx, SwfdecAsObject *object,
     swfdec_movie_global_to_local (movie, &x, &y);
 
     if (shape) {
-      ret = swfdec_movie_mouse_in (movie, x, y);
+      ret = swfdec_movie_contains (movie, x, y);
     } else {
       ret = swfdec_rect_contains (&movie->original_extents, x, y);
     }


More information about the Swfdec mailing list