Plug more leaks (in the test, not the core)
[gnash.git] / libcore / movie_root.h
bloba3b61792819430e8e73661ade298409cf8ec911a
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
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.
9 //
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.
14 //
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
21 ///
22 /// There are two kinds of events:
23 /// - system generated
24 /// - user generated
25 ///
26 /// System generated events are those like load, data recive, unload,
27 /// enter frame, etc.
28 /// User generated events are mouse movements and clicks, keyboard activity.
29 ///
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...
36 ///
37 /// Well, *some* events actions always trigger immediate redisplay, while
38 /// some others require a call to a special function to do so.
39 ///
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 >>
43 ///
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()'.
48 ///
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.
52 ///
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 :)
55 ///
56 /// The events notification functions that currently support this interface
57 /// are:
58 ///
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
67 #ifdef HAVE_CONFIG_H
68 #include "gnashconfig.h" //USE_SWFTREE
69 #endif
71 #include <map>
72 #include <string>
73 #include <vector>
74 #include <list>
75 #include <set>
76 #include <bitset>
77 #include <boost/array.hpp>
78 #include <boost/ptr_container/ptr_deque.hpp>
79 #include <boost/noncopyable.hpp>
80 #include <boost/any.hpp>
82 #include "smart_ptr.h"
83 #include "dsodefs.h" // DSOEXPORT
84 #include "MouseButtonState.h" // for composition
85 #include "DragState.h" // for composition
86 #include "GnashKey.h" // key::code
87 #include "Movie.h"
88 #include "GnashEnums.h"
89 #include "MovieClip.h"
90 #include "SimpleBuffer.h" // for LoadCallback
91 #include "MovieLoader.h"
92 #include "ExternalInterface.h"
93 #include "GC.h"
94 #include "VM.h"
95 #include "HostInterface.h"
96 #include "log.h"
98 #ifdef USE_SWFTREE
99 # include "tree.hh"
100 #endif
102 // GNASH_PARANOIA_LEVEL:
103 // 0 : (not unimplemented)
104 // 1 : quick assertions
105 // 2 : add testInvariant
107 #ifndef GNASH_PARANOIA_LEVEL
108 # define GNASH_PARANOIA_LEVEL 1
109 #endif
111 // Forward declarations
112 namespace gnash {
113 class ExecutableCode;
114 class URL;
115 class Timer;
116 class MovieClip;
117 class VirtualClock;
118 class IOChannel;
119 class RunResources;
120 class Button;
121 class VM;
124 namespace gnash {
126 struct DepthComparator
128 typedef MovieClip* LevelMovie;
129 bool operator()(const LevelMovie& d1, const LevelMovie& d2) const {
130 return d1->get_depth() < d2->get_depth();
134 /// This class represents the 'Stage' and top-level movie.
136 /// It is a wrapper around the set of loaded levels being played. Each
137 /// 'run' of a SWF movie, including all further movies loaded during the
138 /// run, has exactly one movie_root, which is kept for the entire run.
139 /// Loading a new top-level movie does not create a new movie_root.
141 /// The 'Stage' part of movie_root is accessible through the ActionScript
142 /// Stage object, implemented in Stage_as.cpp.
144 /// The movie_root class is responsible for accepting and passing on
145 /// user events (mouse or key events), for maintaining the heart-beat
146 /// mechanism, and for advancing all MovieClips on request from the
147 /// hosting application.
149 /// The _root object is provided by getAsRoot().
150 class DSOEXPORT movie_root : public GcRoot, boost::noncopyable
152 public:
154 /// Listeners container
155 typedef std::list<Button*> Listeners;
157 class LoadCallback {
158 public:
159 LoadCallback(boost::shared_ptr<IOChannel> s, as_object* o)
161 _stream(s),
162 _obj(o)
164 bool processLoad();
165 void setReachable() const;
166 private:
167 boost::shared_ptr<IOChannel> _stream;
168 SimpleBuffer _buf;
169 as_object* _obj;
171 typedef std::list<LoadCallback> LoadCallbacks;
173 typedef std::bitset<key::KEYCOUNT> Keys;
175 /// Default constructor
177 /// Make sure to call setRootMovie()
178 /// before using any of this class methods !
180 movie_root(const movie_definition& def, VirtualClock& clock,
181 const RunResources& runResources);
183 ~movie_root();
185 /// Initialize movie_root with a parsed movie definition
187 /// The definition may be a SWF or Bitmap movie definition.
189 /// The created Movie is returned; it is non-const so may be stored,
190 /// queried, and changed by the caller for debugging or manipulation.
191 /// Direct use of the pointer may result in unexpected behaviour during
192 /// SWF playback, so for normal playback this pointer should not be
193 /// used.
194 Movie* init(movie_definition* def,
195 const MovieClip::MovieVariables& variables);
197 /// Return the movie at the given level (0 if unloaded level).
199 /// POST CONDITIONS:
200 /// - The returned DisplayObject has a depth equal to 'num'
202 MovieClip* getLevel(unsigned int num) const;
204 /// Put the given movie at the given level
206 /// @param movie
207 /// The Movie to store at the given level.
208 /// Its depth will be set to <num>+DisplayObject::staticDepthOffset and
209 /// its name to _level<num>
210 void setLevel(unsigned int num, Movie* movie);
212 /// Replace an existing level with a new movie
214 /// Depth will be assigned to external_movie by this function.
215 /// If the give level number doesn't exist an error is logged
216 /// and nothing else happens.
218 /// This method is intended for use by xxx.loadMovie(yyy)
219 /// when 'xxx' is a top-level movie.
221 void replaceLevel(unsigned int num, Movie* external_movie);
223 /// Swap depth of a level (or two)
225 /// Character's depths are updated.
227 /// @param sp
228 /// The level to change depth/level of. A pointer to it is expected
229 /// to be found in the _level# container, or an error will be printed
230 /// and the call would result in a no-op.
232 /// @param depth
233 /// New depth to assign to the DisplayObject. If another level
234 /// exists at the target depth the latter is moved in place of
235 /// the former, with its depth also updated.
237 void swapLevels(MovieClip* sp, int depth);
239 /// Drop level at given depth.
241 /// @param depth
242 /// Depth of the level to drop. Note that this is
243 /// -DisplayObject::staticDepthOffset for the root movie. Must be >=0 and
244 /// <= 1048575 or an assertion will fail. Note that if the depth
245 /// evaluates to the original root movie nothing happens (not allowed
246 /// to remove that). It is not tested if it's allowed to remove _level0
247 /// after loading into it.
248 void dropLevel(int depth);
250 /// Change stage size
252 /// This may be smaller than the size of the root movie. It determines
253 /// how much of the movie is visible.
255 /// @param w The width of the stage
256 /// @param h The height of the stage.
257 void setDimensions(size_t w, size_t h);
259 /// Notional width of the stage, actual value depending on scaleMode
260 size_t getStageWidth() const;
262 /// Notional height of the stage, actual value depending on scaleMode
263 size_t getStageHeight() const;
265 /// Inform the Stage that the mouse has moved.
267 /// Coordinates are in Stage Coordinate Space (pseudo-pixels units).
269 /// @param x The x co-ordinate in pixels.
270 /// @param y The y co-ordinate in pixels.
271 /// @return true if any action triggered requires a redraw.
273 /// TODO: take twips (or float pixels), or we won't be able to
274 /// support sub-pixel accuracy in collision detection.
275 DSOEXPORT bool mouseMoved(boost::int32_t x, boost::int32_t y);
277 /// Inform the Stage that a mouse click has occurred.
279 /// @param press true for a mouse click, false for a release
280 /// @return true if any action triggered requires a redraw.
281 DSOEXPORT bool mouseClick(bool press);
283 /// Inform the Stage that a mouse wheel has moved.
285 /// @param delta The direction of the scroll: positive for up, negative
286 /// for down. Although values from about -3 to 3 are
287 /// documented, only -1 and 1 have been observed.
288 /// @return true if any action triggered requires a redraw.
289 DSOEXPORT bool mouseWheel(int delta);
291 /// Tell the movie when the user pressed or released a key.
293 /// This function should return TRUE if any action triggered
294 /// by the event requires redraw, see \ref events_handling for
295 /// more info.
296 DSOEXPORT bool keyEvent(key::code k, bool down);
298 /// Use this to retrieve the last state of the mouse.
300 /// Coordinates are in PIXELS, NOT TWIPS.
301 std::pair<boost::int32_t, boost::int32_t> mousePosition() const;
303 void setDragState(const DragState& st);
305 /// Access the originating root movie (not necessarily _level0)
307 /// @return the original root movie.
308 Movie& getRootMovie() {
309 return *_rootMovie;
312 /// Return the current nominal frame rate for the Stage.
314 /// This is dependent on the Movie set as root movie.
315 float frameRate() const {
316 return _rootMovie->frameRate();
319 void stop_drag() {
320 _dragState.reset();
323 /// Add an interval timer
325 /// @param timer
326 /// A Timer, ownership will be transferred. Must not be NULL.
328 /// @param internal
329 /// If true, this is an internal timer, so will get a negative id.
331 /// @return An integer indentifying the timer
332 /// for subsequent call to clear_interval_timer.
333 /// It will NEVER be zero.
334 boost::uint32_t addIntervalTimer(std::auto_ptr<Timer> timer);
336 /// Register an object for loading data to.
338 /// When complete, the object's onData function is called.
339 /// The callback is removed when the load is complete, including failed
340 /// loads.
342 /// There is no restriction on the type of as_object that can registered.
344 /// @param obj The object to update when data is received.
345 /// @param str The stream to load from.
347 /// TODO: this function could be improved, e.g. by handling the
348 /// URL checking and stream construction as well.
350 /// It may be possible for this function to handle all connections if
351 /// it also takes a callback function to call on each advance.
352 void addLoadableObject(as_object* obj, std::auto_ptr<IOChannel> str);
354 void addAdvanceCallback(ActiveRelay* obj);
356 void removeAdvanceCallback(ActiveRelay* obj);
358 /// Remove timer identified by given integer
360 /// @return true on success, false on error (no such timer)
361 bool clearIntervalTimer(boost::uint32_t x);
363 /// Return 0-based frame index of originating root movie
365 /// TODO: drop this function (currently used by gprocessor)
366 /// or change it to to delegate to _level0 ?
368 size_t get_current_frame() const {
369 return _rootMovie->get_current_frame();
372 void set_background_color(const rgba& color);
374 void set_background_alpha(float alpha);
376 /// Return the VM used by this movie_root
377 VM& getVM() { return _vm; }
379 /// Main and only callback from hosting application.
380 /// Expected to be called at 10ms resolution.
382 /// @return true if the heart-beat resulted in actual
383 /// SWF playhead advancement (frame advancement)
385 bool advance();
387 /// \brief
388 /// Return the number of milliseconds available before
389 /// it's time to advance the timeline again.
391 /// Return value can be negative if we're late...
393 int timeToNextFrame() const;
395 /// Entry point for movie advancement
397 /// This function does:
398 /// - Execute all timers
399 /// - Reset the next Random number
400 /// - Advance all advanceable DisplayObjects in reverse-placement order
401 /// - Cleanup key listeners
402 /// - Process all queued actions
403 /// - Remove unloaded DisplayObjects from the advanceable
404 /// DisplayObjects list.
405 /// - Run the GC collector
406 void advanceMovie();
408 /// 0-based!! delegates to originating root movie
410 /// TODO: drop this method. currently used by gprocessor.
411 void goto_frame(size_t target_frame_number) {
412 _rootMovie->goto_frame(target_frame_number);
415 void display();
417 /// Get a unique number for unnamed instances.
418 size_t nextUnnamedInstance() {
419 return ++_unnamedInstance;
422 /// Push a new DisplayObject listener for key events
423 void add_key_listener(Button* listener);
425 /// Remove a DisplayObject listener for key events
426 void remove_key_listener(Button* listener);
428 /// Get the DisplayObject having focus
430 /// The DisplayObject having focus will receive mouse button
431 /// and key presses/releases.
433 /// @return the DisplayObject having focus or NULL of none.
435 DisplayObject* getFocus();
437 /// Set the DisplayObject having focus
439 /// @param to
440 /// The DisplayObject to receive focus. NULL to kill focus.
441 /// @return true if the focus operation succeeded, false if the passed
442 /// DisplayObject cannot receive focus. setFocus(0) is a valid operation, so
443 /// returns true (always succeeds).
444 bool setFocus(DisplayObject* to);
446 DSOEXPORT void add_invalidated_bounds(InvalidatedRanges& ranges,
447 bool force);
449 /// Return the topmost active entity under the pointer
451 /// This method returns cached info, with cache updated
452 /// by notify_mouse_moved (and should be updated also
453 /// by movie advancement or actions execution maybe, not
454 /// currently implmented).
456 /// @return the topmost active entity under pointer or NULL if none.
457 DisplayObject* getActiveEntityUnderPointer() const;
459 /// Return the topmost non-dragging entity under the pointer
461 /// This method triggers a displaylist scan
463 /// @return the topmost non-dragging entity under pointer or NULL if none
464 const DisplayObject* getEntityUnderPointer() const;
466 /// Return the DisplayObject currently being dragged, if any
467 DisplayObject* getDraggingCharacter() const;
469 bool testInvariant() const;
471 /// The possible values of Stage.displayState
472 enum DisplayState {
473 DISPLAYSTATE_NORMAL,
474 DISPLAYSTATE_FULLSCREEN
477 /// The possibile values of Stage.scaleMode
478 enum ScaleMode {
479 SCALEMODE_SHOWALL,
480 SCALEMODE_NOSCALE,
481 SCALEMODE_EXACTFIT,
482 SCALEMODE_NOBORDER
485 /// The possible horizonal positions of the Stage
486 enum StageHorizontalAlign {
487 STAGE_H_ALIGN_C,
488 STAGE_H_ALIGN_L,
489 STAGE_H_ALIGN_R
492 /// The possible vertical position of the Stage
493 enum StageVerticalAlign {
494 STAGE_V_ALIGN_C,
495 STAGE_V_ALIGN_T,
496 STAGE_V_ALIGN_B
499 /// The possible elements of a Stage.alignMode.
500 enum AlignMode {
501 STAGE_ALIGN_L,
502 STAGE_ALIGN_T,
503 STAGE_ALIGN_R,
504 STAGE_ALIGN_B
507 /// The possibile values of AllowScriptAccess
508 enum AllowScriptAccessMode {
509 SCRIPT_ACCESS_NEVER,
510 SCRIPT_ACCESS_SAME_DOMAIN,
511 SCRIPT_ACCESS_ALWAYS
514 /// Set the current display quality of the entire SWF.
515 void setQuality(Quality q);
517 /// Get the current display quality.
518 Quality getQuality() const { return _quality; }
520 /// Sets movie_root's horizontal and vertical alignment to one
521 /// of the three possible positions for each dimension.
522 void setStageAlignment(short s);
524 /// Sets the flag to allow interfacing with JavaScript in the browser.
525 /// This is disabled by default, but enabled for ExternalInterface.
526 void setAllowScriptAccess(AllowScriptAccessMode mode);
528 /// Gets the current Access Mode for ExternalInterface.
529 AllowScriptAccessMode getAllowScriptAccess();
531 typedef std::pair<StageHorizontalAlign, StageVerticalAlign> StageAlign;
533 /// Returns the current alignment of the stage (left/right/centre, top/
534 /// bottom/centre) as a std::pair
535 StageAlign getStageAlignment() const;
537 /// Returns the current value of _showMenu which instructs the gui about
538 /// how much to display in the context menu
539 bool getShowMenuState() const;
541 /// Sets the value of _showMenu and calls the fscommand handler for the
542 /// current gui
543 void setShowMenuState(bool state);
545 /// Sets the Stage object's align mode.
546 void setStageScaleMode(ScaleMode sm);
548 /// Returns the Stage object's align mode.
549 ScaleMode getStageScaleMode() const { return _scaleMode; }
551 // The string representation of the current align mode.
552 std::string getStageAlignMode() const;
554 /// Returns the Stage object's align mode.
555 DisplayState getStageDisplayState() const { return _displayState; }
557 // The string representation of the current align mode.
558 void setStageDisplayState(const DisplayState ds);
560 /// Action priority levels
561 enum ActionPriorityLevel {
562 /// Init actions, Init event handlers
563 PRIORITY_INIT,
564 /// Construct event handlers
565 PRIORITY_CONSTRUCT,
566 /// Frame actions, load handlers, unload handlers
567 PRIORITY_DOACTION,
568 /// Last element used to easy computation of size...
569 PRIORITY_SIZE
572 /// A number of queues of code to execute
574 /// This is a ptr_deque because it needs no insertion in the middle but
575 /// frequent push_back and pop_front. We also have to traverse it, so
576 /// a queue is not usable.
577 typedef boost::array<boost::ptr_deque<ExecutableCode>, PRIORITY_SIZE>
578 ActionQueue;
580 /// Push an executable code to the ActionQueue
581 void pushAction(std::auto_ptr<ExecutableCode> code, size_t lvl);
583 /// Push an executable code to the ActionQueue
584 void pushAction(const action_buffer& buf, DisplayObject* target);
586 /// Mark all reachable resources (for GC)
588 /// Resources reachable from movie_root are:
590 /// - All _level# movies (_movies)
591 /// - The original root movie (_rootMovie)
592 /// - Mouse entities (m_mouse_button_state)
593 /// - Timer targets (_intervalTimers)
594 /// - Resources reachable by ActionQueue code (_actionQueue)
595 /// - Key listeners (_keyListeners)
596 /// - Any DisplayObject being dragged
598 void markReachableResources() const;
600 /// \brief
601 /// Register a newly born advanceable DisplayObject to the
602 /// list of DisplayObjects to be advanced on next ::advance call.
604 /// The DisplayObject will only be advanced if not unloaded when
605 /// its turn comes. Characters are advanced in reverse-placement
606 /// order (first registered is advanced last)
608 void addLiveChar(MovieClip* ch)
610 // Don't register the object in the list twice
611 #if GNASH_PARANOIA_LEVEL > 1
612 assert(std::find(_liveChars.begin(), _liveChars.end(), ch) ==
613 _liveChars.end());
614 #endif
615 _liveChars.push_front(ch);
618 /// Reset stage to its initial state
619 void reset();
621 /// Call this method for disabling run of actions
623 /// NOTE: this will only work for queued actions, not
624 /// for *every* action. Supposedly all actions should
625 /// be queued, but this is not really always the case.
626 /// Notable exceptions are:
627 /// - Actions in callFrame target frame
628 /// but only executed by execution of the callFrame opcode
629 /// - on{,Clip}{Initialize,Construct} event handlers
630 /// - User event handlers (mouse,keyboard)
632 void disableScripts();
634 /// Return true if scripts execution is disabled
635 bool scriptsDisabled() const { return _disableScripts; };
637 /// Process action queues with higher priority then the priority
638 /// of the action queue currently being processed.
640 /// This is intended to be called at the end of any function call
641 /// and at the end of an action block.
643 /// TODO: be aware of infinite loops !
645 void flushHigherPriorityActionQueues();
647 DisplayObject* findCharacterByTarget(const std::string& tgtstr) const;
649 /// Queue a request for loading a movie
651 /// This function constructs the URL and, if required, the postdata
652 /// from the arguments. The variables to send should *not* be appended
653 /// to @param urlstr before calling this function.
655 /// @param urlstr The url exactly as requested. This may already
656 /// contain a query string.
657 /// @param target Target for request.
658 /// @param data The variables data to send, URL encoded in
659 /// key/value pairs
660 /// @param method The VariablesMethod to use for sending the data. If
661 /// MovieClip::METHOD_NONE, no data will be sent.
662 /// @param handler An object which will be signalled of load
663 /// events (onLoadStart, onLoadComplete, onLoadInit,
664 /// onLoadError). Can be null if caller doesn't care.
665 ///
666 void loadMovie(const std::string& url, const std::string& target,
667 const std::string& data, MovieClip::VariablesMethod method,
668 as_object* handler=0)
670 _movieLoader.loadMovie(url, target, data, method, handler);
673 /// Send a request to the hosting application (e.g. browser).
675 /// This function constructs the URL and, if required, the postdata
676 /// from the arguments. The variables to send should *not* be appended
677 /// to @param urlstr before calling this function.
679 /// @param urlstr The url exactly as requested. This may already
680 /// contain a query string.
681 /// @param target Target for request.
682 /// @param data The variables data to send, URL encoded in
683 /// key/value pairs
684 /// @param method The VariablesMethod to use for sending the data. If
685 /// MovieClip::METHOD_NONE, no data will be sent.
686 void getURL(const std::string& urlstr, const std::string& target,
687 const std::string& data, MovieClip::VariablesMethod method);
690 key::code lastKeyEvent() const {
691 return _lastKeyEvent;
694 const Keys& unreleasedKeys() const {
695 return _unreleasedKeys;
698 /// Set a filedescriptor to use for host application requests
699 /// (for browser communication mostly)
700 void setHostFD(int fd) {
701 assert(fd >= 0);
702 _hostfd = fd;
705 /// Set a filedescriptor to use for host application requests
706 /// (for browser communication mostly)
707 void setControlFD(int fd) {
708 _controlfd = fd;
711 /// Get the filedescriptor to use for host application requests
712 /// (for browser communication mostly)
714 /// @return -1 if no filedescriptor is provided by host app.
715 int getHostFD() const {
716 return _hostfd;
719 int getControlFD() const {
720 return _controlfd;
723 /// ActionScript embedded in a movie can use the built-in
724 /// fscommand() function to send data back to the host
725 /// application. If you are interested in this data, register
726 /// a handler, which will be called when the embedded scripts
727 /// call fscommand().
729 /// The handler gets the MovieClip* that the script is
730 /// embedded in, and the two string arguments passed by the
731 /// script to fscommand().
732 DSOEXPORT void registerFSCommandCallback(FsCallback* handler) {
733 _fsCommandHandler = handler;
736 /// Call this to notify FS commands
737 DSOEXPORT void handleFsCommand(const std::string& cmd,
738 const std::string& arg) const;
740 /// A callback to the GUI (or whatever is listening) for sending
741 /// events and receiving replies. Used for ActionScript interface
742 /// with the gui (Mouse visibility, Stage alignment etc and System
743 /// information, for instance).
745 /// See callInterface method
746 DSOEXPORT void registerEventCallback(HostInterface* handler) {
747 _interfaceHandler = handler;
750 /// Call the hosting application without expecting a reply.
752 /// @param e The message to send to the interface.
753 void callInterface(const HostInterface::Message& e) const;
755 /// Call the hosting application, ensuring a return of the requested type.
757 /// If the return type is other than the requested type, this represents
758 /// a bug in the hosting application. An error is logged and the default
759 /// constructed type T is returned. This may cause unexpected
760 /// ActionScript behaviour, but is otherwise safe.
762 /// @tparam T The return type expected.
763 /// @param e The message to send to the interface.
764 template<typename T> T callInterface(const HostInterface::Message& e) const;
766 /// Called from the ScriptLimits tag parser to set the
767 /// global script limits. It is expected behaviour that
768 /// each new loaded movie should override this.
769 /// Can be overridden from gnashrc.
771 /// @param recursion the maximum number of recursions when
772 /// finding 'super'.
773 /// The default value for this (i.e. when no
774 /// ScriptLimits tag is present) is documented to be
775 /// 256, but this may change and appears not to be
776 /// crucial for (backward) compatibility.
777 /// @param timeout the timeout in seconds for script execution.
778 /// The default value for this (i.e. when no
779 /// ScriptLimits tag is present) is documented to be
780 /// 15 to 20 seconds, depending on platform.
781 void setScriptLimits(boost::uint16_t recursion, boost::uint16_t timeout);
783 /// Get the current global recursion limit for this movie: it can
784 /// be changed by loaded movies.
785 boost::uint16_t getRecursionLimit() const {
786 return _recursionLimit;
789 /// Get the current global script timeout limit for this movie: it
790 /// can be changed by loaded movies.
791 boost::uint16_t getTimeoutLimit() const
793 return _timeoutLimit;
796 #ifdef USE_SWFTREE
797 typedef tree<std::pair<std::string, std::string> > InfoTree;
798 void getMovieInfo(InfoTree& tr, InfoTree::iterator it);
799 void getCharacterTree(InfoTree& tr, InfoTree::iterator it);
800 #endif
802 const RunResources& runResources() const { return _runResources; }
804 /// Add an ExternalInterface callback object with an associated name.
805 void addExternalCallback(const std::string& name, as_object* callback);
807 bool processInvoke(ExternalInterface::invoke_t *);
809 std::string callExternalCallback(const std::string &name,
810 const std::vector<as_value>& args);
812 std::string callExternalJavascript(const std::string &name,
813 const std::vector<as_value>& args);
815 /// Removes a queued constructor from the execution queue
817 /// This is used to prevent construction of targets that are placed and
818 /// then removed in skipped frames. Callers are responsible for determining
819 /// whether it should be removed, for instance by checking for an
820 /// onUnload handler.
821 void removeQueuedConstructor(DisplayObject* target);
823 GC& gc() {
824 return _gc;
827 private:
829 /// Set the root movie, replacing the current one if any.
831 /// This is needed for the cases in which the top-level movie
832 /// is replaced by another movie by effect of a loadMovie call
833 /// or similar.
835 /// TODO: inspect what happens about VM version
836 /// (should the *new* movie drive VM operations?
837 /// -- hope not ! )
839 /// Make sure to call this method before using the movie_root,
840 /// as most operations are delegated to the associated/wrapped
841 /// Movie.
843 /// Note that the display viewport will be updated to match
844 /// the size of given movie.
846 /// A call to this method is equivalent to a call to setLevel(0, movie).
848 /// @param movie
849 /// The Movie to wrap.
850 /// Must have a depth of 0.
852 void setRootMovie(Movie* movie);
854 /// Handle mouse events.
855 bool notify_mouse_listeners(const event_id& event);
857 /// This function should return TRUE iff any action triggered
858 /// by the event requires redraw, see \ref events_handling for
859 /// more info.
860 bool fire_mouse_event();
862 /// Take care of dragging, if needed
863 void doMouseDrag();
865 /// Execute expired timers
866 void executeAdvanceCallbacks();
868 /// Execute expired timers
869 void executeTimers();
871 /// Cleanup references to unloaded DisplayObjects and run the GC.
872 void cleanupAndCollect();
874 /// \brief
875 /// Return the topmost entity covering the given point
876 /// and enabled to receive mouse events.
878 /// Return NULL if no "active" entity is found under the pointer.
880 /// Coordinates of the point are given in world coordinate space.
881 /// (twips)
883 /// @param x
884 /// X ordinate of the pointer, in world coordinate space (twips)
886 /// @param y
887 /// Y ordinate of the pointer, in world coordiante space (twips).
889 InteractiveObject* getTopmostMouseEntity(boost::int32_t x,
890 boost::int32_t y) const;
892 /// Delete DisplayObjects removed from the stage
893 /// from the display lists
894 void cleanupDisplayList();
896 /// Advance all non-unloaded live chars
897 void advanceLiveChars();
899 /// Boundaries of the Stage are always world boundaries
900 /// and are only invalidated by changes in the background
901 /// color.
902 void setInvalidated() { _invalidated = true; }
904 /// Every ::display call clears the invalidated flag
906 /// See setInvalidated();
908 void clearInvalidated() { _invalidated = false; }
910 /// An invalidated stage will trigger complete redraw
912 /// So, this method should return true everytime a complete
913 /// redraw is needed. This is typically only needed when
914 /// the background changes.
916 /// See setInvalidated() and clearInvalidated().
918 bool isInvalidated() { return _invalidated; }
920 /// Return the priority level of first action queue containing actions.
922 /// Scanned in proprity order (lower first)
924 size_t minPopulatedPriorityQueue() const;
926 /// Process all actions in the the given queue, till more actions
927 /// are found in lower levels, in which case we have an earlier
928 /// return.
929 size_t processActionQueue(size_t lvl);
931 bool processingActions() const {
932 return (_processingActionLevel < PRIORITY_SIZE);
935 const DisplayObject* findDropTarget(boost::int32_t x, boost::int32_t y,
936 DisplayObject* dragging) const;
938 void handleActionLimitHit(const std::string& ref);
940 /// Buttons listening for key events
942 /// Note that Buttons (the only key listeners left) deregister themselves
943 /// on destruction. This isn't correct behaviour and also requires that
944 /// _keyListeners be alive longer than _gc so that deregistration doesn't
945 /// access a destroyed object.
947 /// TODO: fix it.
948 Listeners _keyListeners;
950 GC _gc;
952 const RunResources& _runResources;
954 /// This initializes a SharedObjectLibrary, which requires
955 /// _baseURL, so that must be initialized first.
956 VM _vm;
958 /// Registered Interface command handler, if any
959 HostInterface* _interfaceHandler;
961 /// Registered FsCommand handler, if any
962 FsCallback* _fsCommandHandler;
964 /// A list of AdvanceableCharacters
966 /// This is a list (not a vector) as we want to allow
967 /// ::advance of each element to insert new DisplayObjects before
968 /// the start w/out invalidating iterators scanning the
969 /// list forward for proper movie advancement
970 typedef std::list<MovieClip*> LiveChars;
972 /// The list of advanceable DisplayObject, in placement order
973 LiveChars _liveChars;
975 ActionQueue _actionQueue;
977 /// Process all actions in the queue
978 void processActionQueue();
980 /// Width and height of viewport, in pixels
981 size_t _stageWidth;
982 size_t _stageHeight;
984 rgba m_background_color;
985 bool m_background_color_set;
987 boost::int32_t _mouseX;
988 boost::int32_t _mouseY;
990 MouseButtonState _mouseButtonState;
992 /// Objects requesting a callback on every movie_root::advance()
993 typedef std::set<ActiveRelay*> ObjectCallbacks;
994 ObjectCallbacks _objectCallbacks;
996 LoadCallbacks _loadCallbacks;
998 typedef std::map<boost::uint32_t, boost::shared_ptr<Timer> > TimerMap;
1000 TimerMap _intervalTimers;
1002 size_t _lastTimerId;
1004 /// bit-array for recording the unreleased keys
1005 Keys _unreleasedKeys;
1007 key::code _lastKeyEvent;
1009 /// The DisplayObject currently holding focus, or 0 if no focus.
1010 DisplayObject* _currentFocus;
1012 /// @todo fold this into m_mouse_button_state?
1013 DragState _dragState;
1015 typedef std::map<int, MovieClip*> Levels;
1017 /// The movie instance wrapped by this movie_root
1019 /// We keep a pointer to the base MovieClip class
1020 /// to avoid having to replicate all of the base class
1021 /// interface to the Movie class definition
1022 Levels _movies;
1024 /// The root movie. This is initially the same as getLevel(0) but might
1025 /// change during the run. It will be used to setup and retrive initial
1026 /// stage size
1027 Movie* _rootMovie;
1029 /// See setInvalidated
1030 bool _invalidated;
1032 /// This is set to true if execution of scripts
1033 /// aborted due to action limit set or whatever else
1034 bool _disableScripts;
1035 int _processingActionLevel;
1037 /// filedescriptor to write to for host application requests
1039 /// -1 if none
1040 int _hostfd;
1041 int _controlfd;
1043 /// The display quality of the entire movie.
1045 /// This is here, not just in the Renderer, so that AS compatibility
1046 /// does not rely on the presence of a renderer.
1047 Quality _quality;
1049 /// The alignment of the Stage
1050 std::bitset<4u> _alignMode;
1052 AllowScriptAccessMode _allowScriptAccess;
1054 /// Whether to show the menu or not.
1055 bool _showMenu;
1057 /// The current scaling mode of the Stage.
1058 ScaleMode _scaleMode;
1060 /// The current state of the Stage (fullscreen or not).
1061 DisplayState _displayState;
1063 // Maximum number of recursions set in the ScriptLimits tag.
1064 boost::uint16_t _recursionLimit;
1066 // Timeout in seconds for script execution, set in the ScriptLimits tag.
1067 boost::uint16_t _timeoutLimit;
1069 // delay between movie advancement, in milliseconds
1070 size_t _movieAdvancementDelay;
1072 // time of last movie advancement, in milliseconds
1073 size_t _lastMovieAdvancement;
1075 /// The number of the last unnamed instance, used to name instances.
1076 size_t _unnamedInstance;
1078 MovieLoader _movieLoader;
1081 /// Return true if the given string can be interpreted as a _level name
1083 /// @param name
1084 /// The target string.
1085 /// Will be considered case-insensitive if VM version is < 7.
1087 /// @param levelno
1088 /// Output parameter, will be set to the level number, if true is
1089 /// returned
1090 bool isLevelTarget(int version, const std::string& name, unsigned int& levelno);
1092 DSOEXPORT short stringToStageAlign(const std::string& s);
1094 template<typename T>
1096 movie_root::callInterface(const HostInterface::Message& e) const
1098 if (!_interfaceHandler) {
1099 log_error("Hosting application registered no callback for "
1100 "messages, can't call %s(%s)");
1101 return T();
1104 try {
1105 return boost::any_cast<T>(_interfaceHandler->call(e));
1107 catch (const boost::bad_any_cast&) {
1108 log_error(_("Unexpected type from host interface when requesting "
1109 "%1%"), e);
1110 return T();
1115 } // namespace gnash
1117 #endif // GNASH_MOVIE_ROOT_H
1119 // Local Variables:
1120 // mode: C++
1121 // indent-tabs-mode: nil
1122 // End: