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
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
88 #include "GnashEnums.h"
89 #include "MovieClip.h"
90 #include "SimpleBuffer.h" // for LoadCallback
91 #include "MovieLoader.h"
92 #include "ExternalInterface.h"
95 #include "HostInterface.h"
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
111 // Forward declarations
113 class ExecutableCode
;
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
154 /// Listeners container
155 typedef std::list
<Button
*> Listeners
;
159 LoadCallback(boost::shared_ptr
<IOChannel
> s
, as_object
* o
)
165 void setReachable() const;
167 boost::shared_ptr
<IOChannel
> _stream
;
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
);
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
194 Movie
* init(movie_definition
* def
,
195 const MovieClip::MovieVariables
& variables
);
197 /// Return the movie at the given level (0 if unloaded level).
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
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.
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.
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.
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
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() {
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();
323 /// Add an interval timer
326 /// A Timer, ownership will be transferred. Must not be NULL.
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
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)
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
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
);
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
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
,
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
474 DISPLAYSTATE_FULLSCREEN
477 /// The possibile values of Stage.scaleMode
485 /// The possible horizonal positions of the Stage
486 enum StageHorizontalAlign
{
492 /// The possible vertical position of the Stage
493 enum StageVerticalAlign
{
499 /// The possible elements of a Stage.alignMode.
507 /// The possibile values of AllowScriptAccess
508 enum AllowScriptAccessMode
{
510 SCRIPT_ACCESS_SAME_DOMAIN
,
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
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
564 /// Construct event handlers
566 /// Frame actions, load handlers, unload handlers
568 /// Last element used to easy computation of 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
>
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;
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
) ==
615 _liveChars
.push_front(ch
);
618 /// Reset stage to its initial state
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
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.
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
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
) {
705 /// Set a filedescriptor to use for host application requests
706 /// (for browser communication mostly)
707 void setControlFD(int 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 {
719 int getControlFD() const {
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
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
;
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
);
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
);
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
835 /// TODO: inspect what happens about VM version
836 /// (should the *new* movie drive VM operations?
839 /// Make sure to call this method before using the movie_root,
840 /// as most operations are delegated to the associated/wrapped
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).
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
860 bool fire_mouse_event();
862 /// Take care of dragging, if needed
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();
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.
884 /// X ordinate of the pointer, in world coordinate space (twips)
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
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
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.
948 Listeners _keyListeners
;
952 const RunResources
& _runResources
;
954 /// This initializes a SharedObjectLibrary, which requires
955 /// _baseURL, so that must be initialized first.
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
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
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
1029 /// See setInvalidated
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
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.
1049 /// The alignment of the Stage
1050 std::bitset
<4u> _alignMode
;
1052 AllowScriptAccessMode _allowScriptAccess
;
1054 /// Whether to show the menu or not.
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
1084 /// The target string.
1085 /// Will be considered case-insensitive if VM version is < 7.
1088 /// Output parameter, will be set to the level number, if true is
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)");
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 "
1115 } // namespace gnash
1117 #endif // GNASH_MOVIE_ROOT_H
1121 // indent-tabs-mode: nil