Drop the bool operator for ObjectURI, to avoid getting the kind of side-effect that...
[gnash.git] / libcore / movie_root.h
bloba3851b953a9ba34e14ffaeee6aaeb6abb99dbe4d
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 "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
76 #include "Movie.h"
77 #include "gnash.h" // Quality
78 #include "MovieClip.h"
79 #include "SimpleBuffer.h" // for LoadCallback
80 #include "MovieLoader.h"
81 #include "ExternalInterface.h"
83 #ifdef USE_SWFTREE
84 # include "tree.hh"
85 #endif
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
94 #endif
96 #include <map>
97 #include <string>
98 #include <vector>
99 #include <deque>
100 #include <list>
101 #include <set>
102 #include <bitset>
103 #include <boost/noncopyable.hpp>
104 #include <boost/thread/thread.hpp>
106 // Forward declarations
107 namespace gnash {
108 class ExecutableCode; // for ActionQueue
109 class URL;
110 class Timer;
111 class MovieClip;
112 class VirtualClock;
113 class IOChannel;
114 class RunResources;
115 class Button;
118 namespace gnash
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
149 public:
151 /// Listeners container
152 typedef std::list<Button*> Listeners;
154 class LoadCallback {
155 public:
156 LoadCallback(boost::shared_ptr<IOChannel> s, as_object* o)
158 _stream(s),
159 _obj(o)
161 bool processLoad();
162 void setReachable() const;
163 private:
164 boost::shared_ptr<IOChannel> _stream;
165 SimpleBuffer _buf;
166 as_object* _obj;
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);
180 ~movie_root();
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
190 /// used.
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).
197 /// POST CONDITIONS:
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
204 /// @param movie
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.
225 /// @param sp
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.
230 /// @param depth
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.
239 /// @param 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
293 /// more info.
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
308 return *_rootMovie;
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
315 /// in the same way.
316 Movie* topLevelMovie() const
318 return _rootMovie;
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();
328 void stop_drag()
330 m_drag_state.reset();
333 /// Add an interval timer
335 /// @param timer
336 /// A Timer, ownership will be transferred. Must not be NULL.
338 /// @param internal
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
351 /// loads.
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)
398 bool advance();
400 /// \brief
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
419 void advanceMovie();
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);
429 void display();
431 /// Delegate to originating root movie
433 /// TODO: drop ?
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
459 /// @param to
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,
467 bool force);
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
492 enum DisplayState {
493 DISPLAYSTATE_NORMAL,
494 DISPLAYSTATE_FULLSCREEN
497 /// The possibile values of Stage.scaleMode
498 enum ScaleMode {
499 SCALEMODE_SHOWALL,
500 SCALEMODE_NOSCALE,
501 SCALEMODE_EXACTFIT,
502 SCALEMODE_NOBORDER
505 /// The possible horizonal positions of the Stage
506 enum StageHorizontalAlign {
507 STAGE_H_ALIGN_C,
508 STAGE_H_ALIGN_L,
509 STAGE_H_ALIGN_R
512 /// The possible vertical position of the Stage
513 enum StageVerticalAlign {
514 STAGE_V_ALIGN_C,
515 STAGE_V_ALIGN_T,
516 STAGE_V_ALIGN_B
519 /// The possible elements of a Stage.alignMode.
520 enum AlignMode {
521 STAGE_ALIGN_L,
522 STAGE_ALIGN_T,
523 STAGE_ALIGN_R,
524 STAGE_ALIGN_B
527 /// The possibile values of AllowScriptAccess
528 enum AllowScriptAccessMode {
529 SCRIPT_ACCESS_NEVER,
530 SCRIPT_ACCESS_SAME_DOMAIN,
531 SCRIPT_ACCESS_ALWAYS
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
562 /// current gui
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
588 PRIORITY_INIT,
589 /// Construct event handlers
590 PRIORITY_CONSTRUCT,
591 /// Frame actions, load handlers, unload handlers
592 PRIORITY_DOACTION,
593 /// Last element used to easy computation of size...
594 PRIORITY_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);
603 #ifdef GNASH_USE_GC
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
619 /// \brief
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) ==
632 _liveChars.end());
633 #endif
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.
642 void clear();
644 /// Reset stage to its initial state
645 void reset();
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
685 /// key/value pairs
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.
691 ///
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
709 /// key/value pairs
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)
728 assert(fd >= 0);
729 _hostfd = fd;
732 /// Set a filedescriptor to use for host application requests
733 /// (for browser communication mostly)
734 void setControlFD(int fd)
736 _controlfd = 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
745 return _hostfd;
748 int getControlFD() const
750 return _controlfd;
754 /// Abstract base class for FS handlers
755 class AbstractFsCallback {
756 public:
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
782 public:
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
793 /// a question.
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
838 /// finding 'super'.
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;
863 #ifdef USE_SWFTREE
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);
867 #endif
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);
896 private:
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
902 /// or similar.
904 /// TODO: inspect what happens about VM version
905 /// (should the *new* movie drive VM operations?
906 /// -- hope not ! )
908 /// Make sure to call this method before using the movie_root,
909 /// as most operations are delegated to the associated/wrapped
910 /// Movie.
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).
917 /// @param 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
928 /// more info.
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
936 /// run.
937 const std::string _originalURL;
939 /// This initializes a SharedObjectLibrary, which requires
940 /// _originalURL, so that must be initialized first.
941 VM& _vm;
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
950 void doMouseDrag();
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();
967 /// \brief
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.
974 /// (twips)
976 /// @param x
977 /// X ordinate of the pointer, in world coordinate space (twips)
979 /// @param y
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
994 /// color.
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
1021 /// return.
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
1057 size_t _stageWidth;
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
1099 Levels _movies;
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
1103 /// stage size
1104 Movie* _rootMovie;
1106 /// See setInvalidated
1107 bool _invalidated;
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
1116 /// -1 if none
1117 int _hostfd;
1118 int _controlfd;
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.
1124 Quality _quality;
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.
1133 bool _showMenu;
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
1161 /// @param name
1162 /// The target string.
1163 /// Will be considered case-insensitive if VM version is < 7.
1165 /// @param levelno
1166 /// Output parameter, will be set to the level number, if true is
1167 /// returned
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
1176 // Local Variables:
1177 // mode: C++
1178 // indent-tabs-mode: nil
1179 // End: