2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 /// \page events_handling Handling of user events
22 /// There are two kinds of events:
23 /// - system generated
26 /// System generated events are those like load, data recive, unload,
28 /// User generated events are mouse movements and clicks, keyboard activity.
30 /// Events can trigger actions execution, if "handlers" are specified for
31 /// a specific event with ActionScript code.
32 /// The actions triggered by user events are executed *immediately*, not
33 /// at the next frame iteration. Nonetheless, since rendering of the stage
34 /// usually happens at fixed rate (frame rate) you won't see the effects
35 /// of actions execution until next iteration... unless...
37 /// Well, *some* events actions always trigger immediate redisplay, while
38 /// some others require a call to a special function to do so.
40 /// The events actions that trigger immediate redisplay are Button actions.
41 /// Colin Mook, in his "ActionScript - The Definitive Guide" sais:
42 /// << Buttons naturally update between frames >>
44 /// Other events, in particular MovieClip events such as mouseDown, mouseUp,
45 /// mouseMove, keyDown and keyUp don't by default trigger redisplay, unless
46 /// the attached action code makes a call to the special function named
47 /// 'updateAfterEvent()'.
49 /// For this purpose, user events notification functions in gnash core
50 /// library return a boolean value, which tells wheter any action triggered
51 /// by the event requires immediate redisplay.
53 /// At the time of writing (2006-10-19) this is not implemented yet and
54 /// the return code is always TRUE. We shall work on it :)
56 /// The events notification functions that currently support this interface
59 /// - bool movie_root::notify_mouse_moved(int x, int y);
60 /// - bool movie_root::notify_mouse_clicked(bool mouse_pressed, int mask);
61 /// - bool keyEvent(key::code k, bool down);
64 #ifndef GNASH_MOVIE_ROOT_H
65 #define GNASH_MOVIE_ROOT_H
68 #include "gnashconfig.h" //USE_SWFTREE
71 #include "smart_ptr.h" // GNASH_USE_GC
72 #include "dsodefs.h" // DSOEXPORT
73 #include "MouseButtonState.h" // for composition
74 #include "drag_state.h" // for composition
75 #include "GnashKey.h" // key::code
77 #include "gnash.h" // Quality
78 #include "MovieClip.h"
79 #include "SimpleBuffer.h" // for LoadCallback
80 #include "MovieLoader.h"
81 #include "ExternalInterface.h"
87 // GNASH_PARANOIA_LEVEL:
88 // 0 : (not unimplemented)
89 // 1 : quick assertions
90 // 2 : add testInvariant
92 #ifndef GNASH_PARANOIA_LEVEL
93 # define GNASH_PARANOIA_LEVEL 1
103 #include <boost/noncopyable.hpp>
104 #include <boost/thread/thread.hpp>
106 // Forward declarations
108 class ExecutableCode
; // for ActionQueue
121 struct DepthComparator
123 typedef MovieClip
* LevelMovie
;
125 bool operator() (const LevelMovie
& d1
, const LevelMovie
& d2
)
127 return d1
->get_depth() < d2
->get_depth();
131 /// This class represents the 'Stage' and top-level movie.
133 /// It is a wrapper around the set of loaded levels being played. Each
134 /// 'run' of a SWF movie, including all further movies loaded during the
135 /// run, has exactly one movie_root, which is kept for the entire run.
136 /// Loading a new top-level movie does not create a new movie_root.
138 /// The 'Stage' part of movie_root is accessible through the ActionScript
139 /// Stage object, implemented in Stage_as.cpp.
141 /// The movie_root class is responsible for accepting and passing on
142 /// user events (mouse or key events), for maintaining the heart-beat
143 /// mechanism, and for advancing all MovieClips on request from the
144 /// hosting application.
146 /// The _root object is provided by getAsRoot().
147 class DSOEXPORT movie_root
: boost::noncopyable
151 /// Listeners container
152 typedef std::list
<Button
*> Listeners
;
156 LoadCallback(boost::shared_ptr
<IOChannel
> s
, as_object
* o
)
162 void setReachable() const;
164 boost::shared_ptr
<IOChannel
> _stream
;
168 typedef std::list
<LoadCallback
> LoadCallbacks
;
170 typedef std::bitset
<key::KEYCOUNT
> Keys
;
172 /// Default constructor
174 /// Make sure to call setRootMovie()
175 /// before using any of this class methods !
177 movie_root(const movie_definition
& def
, VirtualClock
& clock
,
178 const RunResources
& runResources
);
182 /// Initialize movie_root with a parsed movie definition
184 /// The definition may be a SWF or Bitmap movie definition.
186 /// The created Movie is returned; it is non-const so may be stored,
187 /// queried, and changed by the caller for debugging or manipulation.
188 /// Direct use of the pointer may result in unexpected behaviour during
189 /// SWF playback, so for normal playback this pointer should not be
191 Movie
* init(movie_definition
* def
,
192 const MovieClip::MovieVariables
& variables
,
193 const MovieClip::MovieVariables
& scriptables
);
195 /// Return the movie at the given level (0 if unloaded level).
198 /// - The returned DisplayObject has a depth equal to 'num'
200 MovieClip
* getLevel(unsigned int num
) const;
202 /// Put the given movie at the given level
205 /// The Movie to store at the given level.
206 /// Its depth will be set to <num>+DisplayObject::staticDepthOffset and
207 /// its name to _level<num>
208 void setLevel(unsigned int num
, Movie
* movie
);
210 /// Replace an existing level with a new movie
212 /// Depth will be assigned to external_movie by this function.
213 /// If the give level number doesn't exist an error is logged
214 /// and nothing else happens.
216 /// This method is intended for use by xxx.loadMovie(yyy)
217 /// when 'xxx' is a top-level movie.
219 void replaceLevel(unsigned int num
, Movie
* external_movie
);
221 /// Swap depth of a level (or two)
223 /// Character's depths are updated.
226 /// The level to change depth/level of. A pointer to it is expected
227 /// to be found in the _level# container, or an error will be printed
228 /// and the call would result in a no-op.
231 /// New depth to assign to the DisplayObject. If another level
232 /// exists at the target depth the latter is moved in place of
233 /// the former, with its depth also updated.
235 void swapLevels(MovieClip
* sp
, int depth
);
237 /// Drop level at given depth.
240 /// Depth of the level to drop. Note that this is
241 /// -DisplayObject::staticDepthOffset for the root movie. Must be >=0 and
242 /// <= 1048575 or an assertion will fail. Note that if the depth
243 /// evaluates to the original root movie nothing happens (not allowed
244 /// to remove that). It is not tested if it's allowed to remove _level0
245 /// after loading into it.
246 void dropLevel(int depth
);
248 /// Change stage size
250 /// This may be smaller than the size of the root movie. It determines
251 /// how much of the movie is visible.
253 /// @param w The width of the stage
254 /// @param h The height of the stage.
255 void setDimensions(size_t w
, size_t h
);
257 /// Notional width of the stage, actual value depending on scaleMode
258 size_t getStageWidth() const;
260 /// Notional height of the stage, actual value depending on scaleMode
261 size_t getStageHeight() const;
263 /// Inform the Stage that the mouse has moved.
265 /// Coordinates are in Stage Coordinate Space (pseudo-pixels units).
267 /// @param x The x co-ordinate in pixels.
268 /// @param y The y co-ordinate in pixels.
269 /// @return true if any action triggered requires a redraw.
271 /// TODO: take twips (or float pixels), or we won't be able to
272 /// support sub-pixel accuracy in collision detection.
273 DSOEXPORT
bool mouseMoved(boost::int32_t x
, boost::int32_t y
);
275 /// Inform the Stage that a mouse click has occurred.
277 /// @param press true for a mouse click, false for a release
278 /// @return true if any action triggered requires a redraw.
279 DSOEXPORT
bool mouseClick(bool press
);
281 /// Inform the Stage that a mouse wheel has moved.
283 /// @param delta The direction of the scroll: positive for up, negative
284 /// for down. Although values from about -3 to 3 are
285 /// documented, only -1 and 1 have been observed.
286 /// @return true if any action triggered requires a redraw.
287 DSOEXPORT
bool mouseWheel(int delta
);
289 /// Tell the movie when the user pressed or released a key.
291 /// This function should return TRUE if any action triggered
292 /// by the event requires redraw, see \ref events_handling for
294 DSOEXPORT
bool keyEvent(key::code k
, bool down
);
296 /// Use this to retrieve the last state of the mouse.
298 /// Coordinates are in PIXELS, NOT TWIPS.
299 void get_mouse_state(boost::int32_t& x
, boost::int32_t& y
);
301 void get_drag_state(drag_state
& st
);
303 void set_drag_state(const drag_state
& st
);
305 /// @return the originating root movie (not necessarely _level0)
306 const Movie
& getRootMovie() const
311 /// Creating new MovieClips needs this for now.
313 /// TODO: create MovieClips without this and drop. It's deliberately
314 /// different from getRootMovie() so it doesn't end up getting used
316 Movie
* topLevelMovie() const
321 /// Return the current nominal frame rate for the Stage.
323 /// This is dependent on the Movie set as root movie.
324 float frameRate() const {
325 return _rootMovie
->frameRate();
330 m_drag_state
.reset();
333 /// Add an interval timer
336 /// A Timer, ownership will be transferred. Must not be NULL.
339 /// If true, this is an internal timer, so will get a negative id.
341 /// @return An integer indentifying the timer
342 /// for subsequent call to clear_interval_timer.
343 /// It will NEVER be zero.
345 unsigned int add_interval_timer(std::auto_ptr
<Timer
> timer
);
347 /// Register an object for loading data to.
349 /// When complete, the object's onData function is called.
350 /// The callback is removed when the load is complete, including failed
353 /// There is no restriction on the type of as_object that can registered.
355 /// @param obj The object to update when data is received.
356 /// @param str The stream to load from.
358 /// TODO: this function could be improved, e.g. by handling the
359 /// URL checking and stream construction as well.
361 /// It may be possible for this function to handle all connections if
362 /// it also takes a callback function to call on each advance.
363 void addLoadableObject(as_object
* obj
, std::auto_ptr
<IOChannel
> str
);
365 void addAdvanceCallback(ActiveRelay
* obj
);
367 void removeAdvanceCallback(ActiveRelay
* obj
);
369 /// Remove timer identified by given integer
371 /// @return true on success, false on error (no such timer)
373 bool clear_interval_timer(unsigned int x
);
375 /// Return 0-based frame index of originating root movie
377 /// TODO: drop this function (currently used by gprocessor)
378 /// or change it to to delegate to _level0 ?
380 size_t get_current_frame() const
382 return _rootMovie
->get_current_frame();
385 void set_background_color(const rgba
& color
);
387 void set_background_alpha(float alpha
);
389 /// Return the VM used by this movie_root
390 VM
& getVM() { return _vm
; }
392 /// Main and only callback from hosting application.
393 /// Expected to be called at 10ms resolution.
395 /// @return true if the heart-beat resulted in actual
396 /// SWF playhead advancement (frame advancement)
401 /// Return the number of milliseconds available before
402 /// it's time to advance the timeline again.
404 /// Return value can be negative if we're late...
406 int timeToNextFrame() const;
408 /// Entry point for movie advancement
410 /// This function does:
411 /// - Execute all timers
412 /// - Reset the next Random number
413 /// - Advance all advanceable DisplayObjects in reverse-placement order
414 /// - Cleanup key listeners
415 /// - Process all queued actions
416 /// - Remove unloaded DisplayObjects from the advanceable
417 /// DisplayObjects list.
418 /// - Run the GC collector
421 /// 0-based!! delegates to originating root movie
423 /// TODO: drop this method. currently used by gprocessor.
424 void goto_frame(size_t target_frame_number
)
426 _rootMovie
->goto_frame(target_frame_number
);
431 /// Delegate to originating root movie
434 void set_play_state(MovieClip::PlayState s
)
436 _rootMovie
->setPlayState(s
);
439 /// Get a unique number for unnamed instances.
440 size_t nextUnnamedInstance();
442 /// Push a new DisplayObject listener for key events
443 void add_key_listener(Button
* listener
);
445 /// Remove a DisplayObject listener for key events
446 void remove_key_listener(Button
* listener
);
448 /// Get the DisplayObject having focus
450 /// The DisplayObject having focus will receive mouse button
451 /// and key presses/releases.
453 /// @return the DisplayObject having focus or NULL of none.
455 DisplayObject
* getFocus();
457 /// Set the DisplayObject having focus
460 /// The DisplayObject to receive focus. NULL to kill focus.
461 /// @return true if the focus operation succeeded, false if the passed
462 /// DisplayObject cannot receive focus. setFocus(0) is a valid operation, so
463 /// returns true (always succeeds).
464 bool setFocus(DisplayObject
* to
);
466 DSOEXPORT
void add_invalidated_bounds(InvalidatedRanges
& ranges
,
469 /// Return the topmost active entity under the pointer
471 /// This method returns cached info, with cache updated
472 /// by notify_mouse_moved (and should be updated also
473 /// by movie advancement or actions execution maybe, not
474 /// currently implmented).
476 /// @return the topmost active entity under pointer or NULL if none.
477 DisplayObject
* getActiveEntityUnderPointer() const;
479 /// Return the topmost non-dragging entity under the pointer
481 /// This method triggers a displaylist scan
483 /// @return the topmost non-dragging entity under pointer or NULL if none
484 const DisplayObject
* getEntityUnderPointer() const;
486 /// Return the DisplayObject currently being dragged, if any
487 DisplayObject
* getDraggingCharacter() const;
489 bool testInvariant() const;
491 /// The possible values of Stage.displayState
494 DISPLAYSTATE_FULLSCREEN
497 /// The possibile values of Stage.scaleMode
505 /// The possible horizonal positions of the Stage
506 enum StageHorizontalAlign
{
512 /// The possible vertical position of the Stage
513 enum StageVerticalAlign
{
519 /// The possible elements of a Stage.alignMode.
527 /// The possibile values of AllowScriptAccess
528 enum AllowScriptAccessMode
{
530 SCRIPT_ACCESS_SAME_DOMAIN
,
534 /// Set the current display quality of the entire SWF.
535 void setQuality(Quality q
);
537 /// Get the current display quality.
538 Quality
getQuality() const { return _quality
; }
540 /// Sets movie_root's horizontal and vertical alignment to one
541 /// of the three possible positions for each dimension.
542 void setStageAlignment(short s
);
544 /// Sets the flag to allow interfacing with JavaScript in the browser.
545 /// This is disabled by default, but enabled for ExternalInterface.
546 void setAllowScriptAccess(AllowScriptAccessMode mode
);
548 /// Gets the current Access Mode for ExternalInterface.
549 AllowScriptAccessMode
getAllowScriptAccess();
551 typedef std::pair
<StageHorizontalAlign
, StageVerticalAlign
> StageAlign
;
553 /// Returns the current alignment of the stage (left/right/centre, top/
554 /// bottom/centre) as a std::pair
555 StageAlign
getStageAlignment() const;
557 /// Returns the current value of _showMenu which instructs the gui about
558 /// how much to display in the context menu
559 bool getShowMenuState() const;
561 /// Sets the value of _showMenu and calls the fscommand handler for the
563 void setShowMenuState(bool state
);
565 // This is a flag that specifies whether exceptions in ActionScript
566 // should be propogated to JavaScript in the browser.
567 void setMarshallExceptions(bool x
) { _marshallExceptions
= x
; };
568 bool getMarshallExceptions() { return _marshallExceptions
; };
570 /// Sets the Stage object's align mode.
571 void setStageScaleMode(ScaleMode sm
);
573 /// Returns the Stage object's align mode.
574 ScaleMode
getStageScaleMode() const { return _scaleMode
; }
576 // The string representation of the current align mode.
577 std::string
getStageAlignMode() const;
579 /// Returns the Stage object's align mode.
580 DisplayState
getStageDisplayState() const { return _displayState
; }
582 // The string representation of the current align mode.
583 void setStageDisplayState(const DisplayState ds
);
585 /// Action priority levels
586 enum ActionPriorityLevel
{
587 /// Init actions, Init event handlers
589 /// Construct event handlers
591 /// Frame actions, load handlers, unload handlers
593 /// Last element used to easy computation of size...
597 /// Push an executable code to the ActionQueue
598 void pushAction(std::auto_ptr
<ExecutableCode
> code
, size_t lvl
);
600 /// Push an executable code to the ActionQueue
601 void pushAction(const action_buffer
& buf
, DisplayObject
* target
);
604 /// Mark all reachable resources (for GC)
606 /// Resources reachable from movie_root are:
608 /// - All _level# movies (_movies)
609 /// - The original root movie (_rootMovie)
610 /// - Mouse entities (m_mouse_button_state)
611 /// - Timer targets (_intervalTimers)
612 /// - Resources reachable by ActionQueue code (_actionQueue)
613 /// - Key listeners (_keyListeners)
614 /// - Any DisplayObject being dragged
616 void markReachableResources() const;
617 #endif // GNASH_USE_GC
620 /// Register a newly born advanceable DisplayObject to the
621 /// list of DisplayObjects to be advanced on next ::advance call.
623 /// The DisplayObject will only be advanced if not unloaded when
624 /// its turn comes. Characters are advanced in reverse-placement
625 /// order (first registered is advanced last)
627 void addLiveChar(MovieClip
* ch
)
629 // Don't register the object in the list twice
630 #if GNASH_PARANOIA_LEVEL > 1
631 assert(std::find(_liveChars
.begin(), _liveChars
.end(), ch
) ==
634 _liveChars
.push_front(ch
);
637 /// Cleanup all resources and run the GC collector
639 /// This method should be invoked before calling setRootMovie again
640 /// for a clean restart.
644 /// Reset stage to its initial state
647 /// Call this method for disabling run of actions
649 /// NOTE: this will only work for queued actions, not
650 /// for *every* action. Supposedly all actions should
651 /// be queued, but this is not really always the case.
652 /// Notable exceptions are:
653 /// - Actions in callFrame target frame
654 /// but only executed by execution of the callFrame opcode
655 /// - on{,Clip}{Initialize,Construct} event handlers
656 /// - User event handlers (mouse,keyboard)
658 void disableScripts();
660 /// Return true if scripts execution is disabled
661 bool scriptsDisabled() const { return _disableScripts
; };
663 /// Process action queues with higher priority then the priority
664 /// of the action queue currently being processed.
666 /// This is intended to be called at the end of any function call
667 /// and at the end of an action block.
669 /// TODO: be aware of infinite loops !
671 void flushHigherPriorityActionQueues();
673 DisplayObject
* findCharacterByTarget(const std::string
& tgtstr
) const;
675 /// Queue a request for loading a movie
677 /// This function constructs the URL and, if required, the postdata
678 /// from the arguments. The variables to send should *not* be appended
679 /// to @param urlstr before calling this function.
681 /// @param urlstr The url exactly as requested. This may already
682 /// contain a query string.
683 /// @param target Target for request.
684 /// @param data The variables data to send, URL encoded in
686 /// @param method The VariablesMethod to use for sending the data. If
687 /// MovieClip::METHOD_NONE, no data will be sent.
688 /// @param handler An object which will be signalled of load
689 /// events (onLoadStart, onLoadComplete, onLoadInit,
690 /// onLoadError). Can be null if caller doesn't care.
692 void loadMovie(const std::string
& url
, const std::string
& target
,
693 const std::string
& data
, MovieClip::VariablesMethod method
,
694 as_object
* handler
=0)
696 _movieLoader
.loadMovie(url
, target
, data
, method
, handler
);
699 /// Send a request to the hosting application (e.g. browser).
701 /// This function constructs the URL and, if required, the postdata
702 /// from the arguments. The variables to send should *not* be appended
703 /// to @param urlstr before calling this function.
705 /// @param urlstr The url exactly as requested. This may already
706 /// contain a query string.
707 /// @param target Target for request.
708 /// @param data The variables data to send, URL encoded in
710 /// @param method The VariablesMethod to use for sending the data. If
711 /// MovieClip::METHOD_NONE, no data will be sent.
712 void getURL(const std::string
& urlstr
, const std::string
& target
,
713 const std::string
& data
, MovieClip::VariablesMethod method
);
716 key::code
lastKeyEvent() const {
717 return _lastKeyEvent
;
720 const Keys
& unreleasedKeys() const {
721 return _unreleasedKeys
;
724 /// Set a filedescriptor to use for host application requests
725 /// (for browser communication mostly)
726 void setHostFD(int fd
)
732 /// Set a filedescriptor to use for host application requests
733 /// (for browser communication mostly)
734 void setControlFD(int fd
)
739 /// Get the filedescriptor to use for host application requests
740 /// (for browser communication mostly)
742 /// @return -1 if no filedescriptor is provided by host app.
743 int getHostFD() const
748 int getControlFD() const
754 /// Abstract base class for FS handlers
755 class AbstractFsCallback
{
757 virtual void notify(const std::string
& cmd
, const std::string
& arg
)=0;
758 virtual ~AbstractFsCallback() {}
761 /// ActionScript embedded in a movie can use the built-in
762 /// fscommand() function to send data back to the host
763 /// application. If you are interested in this data, register
764 /// a handler, which will be called when the embedded scripts
765 /// call fscommand().
767 /// The handler gets the MovieClip* that the script is
768 /// embedded in, and the two string arguments passed by the
769 /// script to fscommand().
770 DSOEXPORT
void registerFSCommandCallback(AbstractFsCallback
* handler
)
772 _fsCommandHandler
= handler
;
775 /// Call this to notify FS commands
776 DSOEXPORT
void handleFsCommand(const std::string
& cmd
,
777 const std::string
& arg
) const;
779 /// Abstract base class for hosting app handler
780 class AbstractIfaceCallback
784 /// Get Gui-related information for the core.
786 /// This should be used for occasional AS calls, such as for
787 /// Mouse.hide, System.capabilities etc. The return can be
788 /// various types, so it is passed as a string.
789 virtual std::string
call(const std::string
& cmd
,
790 const std::string
& arg
= std::string()) = 0;
792 /// Ask the hosting application for a yes / no answer to
794 virtual bool yesNo(const std::string
& cmd
) = 0;
796 /// Instruct the hosting application to exit.
797 virtual void exit() = 0;
799 /// Send an error message to the hosting application.
801 /// This does not have to be implemented; the default is a no-op.
802 virtual void error(const std::string
& /*msg*/) {}
804 virtual ~AbstractIfaceCallback() {}
807 /// A callback to the GUI (or whatever is listening) for sending
808 /// events and receiving replies. Used for ActionScript interface
809 /// with the gui (Mouse visibility, Stage alignment etc and System
810 /// information, for instance).
812 /// See callInterface method
813 DSOEXPORT
void registerEventCallback(AbstractIfaceCallback
* handler
)
815 _interfaceHandler
= handler
;
818 /// Call into the hosting application
820 /// Will use callback set with registerEventCallback
821 DSOEXPORT
std::string
callInterface(const std::string
& cmd
,
822 const std::string
& arg
= std::string()) const;
824 /// Send an error message to the hosting application.
826 /// @param msg A message to send describing the error.
828 /// The hosting app decides what to do with the message, or whether it
829 /// wants to do anything at all. It may show a popup box.
830 DSOEXPORT
void errorInterface(const std::string
& msg
) const;
832 /// Called from the ScriptLimits tag parser to set the
833 /// global script limits. It is expected behaviour that
834 /// each new loaded movie should override this.
835 /// Can be overridden from gnashrc.
837 /// @param recursion the maximum number of recursions when
839 /// The default value for this (i.e. when no
840 /// ScriptLimits tag is present) is documented to be
841 /// 256, but this may change and appears not to be
842 /// crucial for (backward) compatibility.
843 /// @param timeout the timeout in seconds for script execution.
844 /// The default value for this (i.e. when no
845 /// ScriptLimits tag is present) is documented to be
846 /// 15 to 20 seconds, depending on platform.
847 void setScriptLimits(boost::uint16_t recursion
, boost::uint16_t timeout
);
849 /// Get the current global recursion limit for this movie: it can
850 /// be changed by loaded movies.
851 boost::uint16_t getRecursionLimit() const
853 return _recursionLimit
;
856 /// Get the current global script timeout limit for this movie: it
857 /// can be changed by loaded movies.
858 boost::uint16_t getTimeoutLimit() const
860 return _timeoutLimit
;
864 typedef std::pair
<std::string
, std::string
> StringPair
;
865 void getMovieInfo(tree
<StringPair
>& tr
, tree
<StringPair
>::iterator it
);
866 void getCharacterTree(tree
<StringPair
>& tr
, tree
<StringPair
>::iterator it
);
869 /// Get URL of the SWF movie used to initialize this VM
871 /// This information will be used for security checks
873 const std::string
& getOriginalURL() const { return _originalURL
; }
875 const RunResources
& runResources() const { return _runResources
; }
877 void addExternalCallback(as_object
*obj
, const std::string
&name
,
878 as_object
*callback
);
880 bool processInvoke(ExternalInterface::invoke_t
*);
882 std::string
callExternalCallback(const std::string
&name
,
883 const std::vector
<as_value
>& args
);
885 std::string
callExternalJavascript(const std::string
&name
,
886 const std::vector
<as_value
>& args
);
888 /// Removes a queued constructor from the execution queue
890 /// This is used to prevent construction of targets that are placed and
891 /// then removed in skipped frames. Callers are responsible for determining
892 /// whether it should be removed, for instance by checking for an
893 /// onUnload handler.
894 void removeQueuedConstructor(DisplayObject
* target
);
898 /// Set the root movie, replacing the current one if any.
900 /// This is needed for the cases in which the top-level movie
901 /// is replaced by another movie by effect of a loadMovie call
904 /// TODO: inspect what happens about VM version
905 /// (should the *new* movie drive VM operations?
908 /// Make sure to call this method before using the movie_root,
909 /// as most operations are delegated to the associated/wrapped
912 /// Note that the display viewport will be updated to match
913 /// the size of given movie.
915 /// A call to this method is equivalent to a call to setLevel(0, movie).
918 /// The Movie to wrap.
919 /// Must have a depth of 0.
921 void setRootMovie(Movie
* movie
);
923 /// Handle mouse events.
924 bool notify_mouse_listeners(const event_id
& event
);
926 /// This function should return TRUE iff any action triggered
927 /// by the event requires redraw, see \ref events_handling for
929 bool fire_mouse_event();
931 const RunResources
& _runResources
;
933 /// The URL of the original root movie.
935 /// This is a runtime constant because it must not change during a
937 const std::string _originalURL
;
939 /// This initializes a SharedObjectLibrary, which requires
940 /// _originalURL, so that must be initialized first.
943 /// Registered Interface command handler, if any
944 AbstractIfaceCallback
* _interfaceHandler
;
946 /// Registered FsCommand handler, if any
947 AbstractFsCallback
* _fsCommandHandler
;
949 /// Take care of dragging, if needed
952 /// Delete all elements on the action queue and empty it.
953 void clearActionQueue();
955 /// Delete all elements on the timers list
956 void clearIntervalTimers();
958 /// Execute expired timers
959 void executeAdvanceCallbacks();
961 /// Execute expired timers
962 void executeTimers();
964 /// Cleanup references to unloaded DisplayObjects and run the GC.
965 void cleanupAndCollect();
968 /// Return the topmost entity covering the given point
969 /// and enabled to receive mouse events.
971 /// Return NULL if no "active" entity is found under the pointer.
973 /// Coordinates of the point are given in world coordinate space.
977 /// X ordinate of the pointer, in world coordinate space (twips)
980 /// Y ordinate of the pointer, in world coordiante space (twips).
982 InteractiveObject
* getTopmostMouseEntity(boost::int32_t x
,
983 boost::int32_t y
) const;
985 /// Delete DisplayObjects removed from the stage
986 /// from the display lists
987 void cleanupDisplayList();
989 /// Advance all non-unloaded live chars
990 void advanceLiveChars();
992 /// Boundaries of the Stage are always world boundaries
993 /// and are only invalidated by changes in the background
995 void setInvalidated() { _invalidated
= true; }
997 /// Every ::display call clears the invalidated flag
999 /// See setInvalidated();
1001 void clearInvalidated() { _invalidated
= false; }
1003 /// An invalidated stage will trigger complete redraw
1005 /// So, this method should return true everytime a complete
1006 /// redraw is needed. This is typically only needed when
1007 /// the background changes.
1009 /// See setInvalidated() and clearInvalidated().
1011 bool isInvalidated() { return _invalidated
; }
1013 /// Return the priority level of first action queue containing actions.
1015 /// Scanned in proprity order (lower first)
1017 size_t minPopulatedPriorityQueue() const;
1019 /// Process all actions in the the given queue, till more actions
1020 /// are found in lower levels, in which case we have an earlier
1022 size_t processActionQueue(size_t lvl
);
1024 bool processingActions() const
1026 return (_processingActionLevel
< PRIORITY_SIZE
);
1029 const DisplayObject
* findDropTarget(boost::int32_t x
, boost::int32_t y
,
1030 DisplayObject
* dragging
) const;
1032 void handleActionLimitHit(const std::string
& ref
);
1034 /// A list of AdvanceableCharacters
1036 /// This is a list (not a vector) as we want to allow
1037 /// ::advance of each element to insert new DisplayObjects before
1038 /// the start w/out invalidating iterators scanning the
1039 /// list forward for proper movie advancement
1040 typedef std::list
<MovieClip
*> LiveChars
;
1042 /// The list of advanceable DisplayObject, in placement order
1043 LiveChars _liveChars
;
1045 /// A number of queues of code to execute
1047 /// This is a deque because it needs no insertion in the middle but
1048 /// frequent push_back and pop_front. We also have to traverse it, so
1049 /// a std::queue is not usable.
1050 typedef std::deque
<ExecutableCode
*> ActionQueue
;
1051 ActionQueue _actionQueue
[PRIORITY_SIZE
];
1053 /// Process all actions in the queue
1054 void processActionQueue();
1056 /// Width and height of viewport, in pixels
1058 size_t _stageHeight
;
1060 rgba m_background_color
;
1061 bool m_background_color_set
;
1063 boost::int32_t _mouseX
;
1064 boost::int32_t _mouseY
;
1066 MouseButtonState _mouseButtonState
;
1068 /// Objects requesting a callback on every movie_root::advance()
1069 typedef std::set
<ActiveRelay
*> ObjectCallbacks
;
1070 ObjectCallbacks _objectCallbacks
;
1072 LoadCallbacks _loadCallbacks
;
1074 typedef std::map
<int, Timer
*> TimerMap
;
1075 TimerMap _intervalTimers
;
1076 unsigned int _lastTimerId
;
1078 /// bit-array for recording the unreleased keys
1079 Keys _unreleasedKeys
;
1081 key::code _lastKeyEvent
;
1083 /// Characters for listening key events
1084 Listeners _keyListeners
;
1086 /// The DisplayObject currently holding focus, or 0 if no focus.
1087 DisplayObject
* _currentFocus
;
1089 /// @todo fold this into m_mouse_button_state?
1090 drag_state m_drag_state
;
1092 typedef std::map
<int, MovieClip
*> Levels
;
1094 /// The movie instance wrapped by this movie_root
1096 /// We keep a pointer to the base MovieClip class
1097 /// to avoid having to replicate all of the base class
1098 /// interface to the Movie class definition
1101 /// The root movie. This is initially the same as getLevel(0) but might
1102 /// change during the run. It will be used to setup and retrive initial
1106 /// See setInvalidated
1109 /// This is set to true if execution of scripts
1110 /// aborted due to action limit set or whatever else
1111 bool _disableScripts
;
1112 int _processingActionLevel
;
1114 /// filedescriptor to write to for host application requests
1120 /// The display quality of the entire movie.
1122 /// This is here, not just in the Renderer, so that AS compatibility
1123 /// does not rely on the presence of a renderer.
1126 /// The alignment of the Stage
1127 std::bitset
<4u> _alignMode
;
1129 AllowScriptAccessMode _allowScriptAccess
;
1130 bool _marshallExceptions
;
1132 /// Whether to show the menu or not.
1135 /// The current scaling mode of the Stage.
1136 ScaleMode _scaleMode
;
1138 /// The current state of the Stage (fullscreen or not).
1139 DisplayState _displayState
;
1141 // Maximum number of recursions set in the ScriptLimits tag.
1142 boost::uint16_t _recursionLimit
;
1144 // Timeout in seconds for script execution, set in the ScriptLimits tag.
1145 boost::uint16_t _timeoutLimit
;
1147 // delay between movie advancement, in milliseconds
1148 size_t _movieAdvancementDelay
;
1150 // time of last movie advancement, in milliseconds
1151 size_t _lastMovieAdvancement
;
1153 /// The number of the last unnamed instance, used to name instances.
1154 size_t _unnamedInstance
;
1156 MovieLoader _movieLoader
;
1159 /// Return true if the given string can be interpreted as a _level name
1162 /// The target string.
1163 /// Will be considered case-insensitive if VM version is < 7.
1166 /// Output parameter, will be set to the level number, if true is
1168 bool isLevelTarget(int version
, const std::string
& name
, unsigned int& levelno
);
1170 DSOEXPORT
short stringToStageAlign(const std::string
& s
);
1172 } // namespace gnash
1174 #endif // GNASH_MOVIE_ROOT_H
1178 // indent-tabs-mode: nil