CVSROOT: /sources/gnash Module name: gnash Changes by: Zou Lunkai <zoulunkai> 07/11/16 07:43:54
Modified files: . : ChangeLog server : as_object.cpp as_object.h button_character_instance.cpp character.h edit_text_character.cpp movie_root.cpp movie_root.h sprite_instance.cpp server/asobj : Key.cpp Key.h testsuite/misc-ming.all: key_event_test.c key_event_testrunner.cpp Log message: * server/as_object.{h,cpp}, server/asobj/Key.{h,cpp}, server/character.h, server/button_character_instance.cpp, server/edit_text_character.cpp, server/movie_root.{h,cpp}, server/sprite_instance.cpp: drop new key listeners design and fix the old design with caring about listeners invoking order. * testsuite/key_event_test.c, key_event_testrunner.cpp: xcheck->check. CVSWeb URLs: http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4874&r2=1.4875 http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_object.cpp?cvsroot=gnash&r1=1.79&r2=1.80 http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_object.h?cvsroot=gnash&r1=1.82&r2=1.83 http://cvs.savannah.gnu.org/viewcvs/gnash/server/button_character_instance.cpp?cvsroot=gnash&r1=1.64&r2=1.65 http://cvs.savannah.gnu.org/viewcvs/gnash/server/character.h?cvsroot=gnash&r1=1.108&r2=1.109 http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character.cpp?cvsroot=gnash&r1=1.130&r2=1.131 http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.cpp?cvsroot=gnash&r1=1.122&r2=1.123 http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.h?cvsroot=gnash&r1=1.87&r2=1.88 http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.cpp?cvsroot=gnash&r1=1.387&r2=1.388 http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Key.cpp?cvsroot=gnash&r1=1.43&r2=1.44 http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Key.h?cvsroot=gnash&r1=1.29&r2=1.30 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/key_event_test.c?cvsroot=gnash&r1=1.6&r2=1.7 http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/misc-ming.all/key_event_testrunner.cpp?cvsroot=gnash&r1=1.14&r2=1.15 Patches: Index: ChangeLog =================================================================== RCS file: /sources/gnash/gnash/ChangeLog,v retrieving revision 1.4874 retrieving revision 1.4875 diff -u -b -r1.4874 -r1.4875 --- ChangeLog 15 Nov 2007 23:38:13 -0000 1.4874 +++ ChangeLog 16 Nov 2007 07:43:52 -0000 1.4875 @@ -1,3 +1,14 @@ +2007-11-16 Zou Lunkai <[EMAIL PROTECTED]> + + * server/as_object.{h,cpp}, server/asobj/Key.{h,cpp}, + server/character.h, + server/button_character_instance.cpp, + server/edit_text_character.cpp, + server/movie_root.{h,cpp}, + server/sprite_instance.cpp: drop new key listeners design and fix the + old design with caring about listeners invoking order. + * testsuite/key_event_test.c, key_event_testrunner.cpp: xcheck->check. + 2007-11-15 Sandro Santilli <[EMAIL PROTECTED]> * testsuite/actionscript.all/ops.as: a couple of tests more. Index: server/as_object.cpp =================================================================== RCS file: /sources/gnash/gnash/server/as_object.cpp,v retrieving revision 1.79 retrieving revision 1.80 diff -u -b -r1.79 -r1.80 --- server/as_object.cpp 30 Oct 2007 18:55:42 -0000 1.79 +++ server/as_object.cpp 16 Nov 2007 07:43:52 -0000 1.80 @@ -808,7 +808,6 @@ return tmp.to_object(); } -#ifdef NEW_KEY_LISTENER_LIST_DESIGN bool as_object::on_event(const event_id& id ) { @@ -829,7 +828,6 @@ return false; } -#endif as_value as_object::getMember(string_table::key name, string_table::key nsname) Index: server/as_object.h =================================================================== RCS file: /sources/gnash/gnash/server/as_object.h,v retrieving revision 1.82 retrieving revision 1.83 diff -u -b -r1.82 -r1.83 --- server/as_object.h 30 Oct 2007 18:55:42 -0000 1.82 +++ server/as_object.h 16 Nov 2007 07:43:52 -0000 1.83 @@ -33,10 +33,7 @@ #include "smart_ptr.h" #include "as_prop_flags.h" // for enum #include "GnashException.h" -#define NEW_KEY_LISTENER_LIST_DESIGN -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - #include "event_id.h" // for event_id -#endif +#include "event_id.h" // for event_id #include <sstream> #if defined(__GNUC__) && __GNUC__ > 2 @@ -246,9 +243,7 @@ std::pair<bool,bool> update_member(string_table::key key, const as_value& val, string_table::key nsname = 0); -#ifdef NEW_KEY_LISTENER_LIST_DESIGN virtual bool on_event(const event_id& id ); -#endif /// Reserve a slot /// Index: server/button_character_instance.cpp =================================================================== RCS file: /sources/gnash/gnash/server/button_character_instance.cpp,v retrieving revision 1.64 retrieving revision 1.65 diff -u -b -r1.64 -r1.65 --- server/button_character_instance.cpp 10 Nov 2007 11:51:42 -0000 1.64 +++ server/button_character_instance.cpp 16 Nov 2007 07:43:53 -0000 1.65 @@ -268,11 +268,7 @@ { if (m_def->m_button_actions[i].m_conditions & 0xFE00) // check up on CondKeyPress: UB[7] { -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - _vm.getRoot().add_key_listener(KeyListener(this, KeyListener::ON_CLIP_DEF)); -#else _vm.getRoot().add_key_listener(this); -#endif break; } } Index: server/character.h =================================================================== RCS file: /sources/gnash/gnash/server/character.h,v retrieving revision 1.108 retrieving revision 1.109 diff -u -b -r1.108 -r1.109 --- server/character.h 10 Nov 2007 11:51:42 -0000 1.108 +++ server/character.h 16 Nov 2007 07:43:53 -0000 1.109 @@ -19,7 +19,7 @@ // // -/* $Id: character.h,v 1.108 2007/11/10 11:51:42 strk Exp $ */ +/* $Id: character.h,v 1.109 2007/11/16 07:43:53 zoulunkai Exp $ */ #ifndef GNASH_CHARACTER_H #define GNASH_CHARACTER_H @@ -195,7 +195,7 @@ { return _event_handlers; } -#ifndef NEW_KEY_LISTENER_LIST_DESIGN + /// Return a user defined event handler, if any // /// @param name @@ -208,7 +208,7 @@ /// casts to an as_function. A NULL pointer otherwise. /// boost::intrusive_ptr<as_function> getUserDefinedEventHandler(const std::string& name) const; -#endif + void set_event_handlers(const Events& copyfrom); /// Used to assign a name to unnamed instances Index: server/edit_text_character.cpp =================================================================== RCS file: /sources/gnash/gnash/server/edit_text_character.cpp,v retrieving revision 1.130 retrieving revision 1.131 diff -u -b -r1.130 -r1.131 --- server/edit_text_character.cpp 10 Nov 2007 11:51:42 -0000 1.130 +++ server/edit_text_character.cpp 16 Nov 2007 07:43:53 -0000 1.131 @@ -17,7 +17,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -/* $Id: edit_text_character.cpp,v 1.130 2007/11/10 11:51:42 strk Exp $ */ +/* $Id: edit_text_character.cpp,v 1.131 2007/11/16 07:43:53 zoulunkai Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -2089,11 +2089,9 @@ m_has_focus = true; -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - _vm.getRoot().add_key_listener(KeyListener(this, KeyListener::ON_CLIP_DEF)); -#else + // why should we add to the key listener list every time + // we call setFocus()??? _vm.getRoot().add_key_listener(this); -#endif m_cursor = _text.size(); format_text(); Index: server/movie_root.cpp =================================================================== RCS file: /sources/gnash/gnash/server/movie_root.cpp,v retrieving revision 1.122 retrieving revision 1.123 diff -u -b -r1.122 -r1.123 --- server/movie_root.cpp 14 Nov 2007 13:23:46 -0000 1.122 +++ server/movie_root.cpp 16 Nov 2007 07:43:53 -0000 1.123 @@ -34,9 +34,6 @@ #include "URL.h" #include "namedStrings.h" #include "GnashException.h" -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - #include "action.h" -#endif #include <iostream> #include <string> @@ -371,19 +368,16 @@ bool movie_root::notify_key_event(key::code k, bool down) { -//GNASH_REPORT_FUNCTION; - // // First of all, notify the _global.Key object about key event // key_as_object * global_key = notify_global_key(k, down); - // Notify character key listeners. + // Notify character key listeners for clip key events notify_key_listeners(k, down); -#ifndef NEW_KEY_LISTENER_LIST_DESIGN + // Notify both character and non-character Key listeners // for user defined handerlers. - // FIXME: this may violates the event order if(global_key) { if(down) @@ -394,7 +388,7 @@ else global_key->notify_listeners(event_id::KEY_UP); } -#endif + processActionQueue(); return false; // should return true if needs update ... @@ -779,12 +773,6 @@ // NOTE: can throw ActionLimitException executeTimers(); -#ifndef NEW_KEY_LISTENER_LIST_DESIGN - // Cleanup key listeners (remove unloaded characters) - // FIXME: not all key listeners could be cleaned here! - // (eg. characters unloaded by loop-back won't be cleared until next advancement) - cleanup_key_listeners(); -#endif // random should go continuously that: // 1. after restart of the player the situation has not repeated // 2. by different machines the random gave different numbers @@ -795,9 +783,7 @@ // NOTE: can throw ActionLimitException advanceLiveChars(delta_time); -#ifdef NEW_KEY_LISTENER_LIST_DESIGN cleanup_key_listeners(); -#endif // Process queued actions // NOTE: can throw ActionLimitException @@ -892,151 +878,15 @@ return getLevel(0)->call_method_args(method_name, method_arg_fmt, args); } -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - -void movie_root::cleanup_key_listeners() -{ -#ifdef KEY_LISTENERS_DEBUG - size_t prevsize = _keyListeners.size(); - log_msg("Cleaning up %u key listeners", _keyListeners.size()); -#endif - - for (KeyListeners::iterator iter = _keyListeners.begin(); - iter != _keyListeners.end(); ) - { - // The listener object has no registered key event handlers, remove it. - if( !iter->hasUserRegistered() && !iter->hasOnClipRegistered() ) - { - _keyListeners.erase(iter++); - } - else - { - boost::intrusive_ptr<as_object> obj = iter->get(); - character* ch = dynamic_cast<character*>(obj.get()); - // The listener object is unloaded, remove it. - // TODO: Don't do this again in the character destructors. should we? - if ( ch && ch->isUnloaded() ) - { - _keyListeners.erase(iter++); - } - else - ++iter; - } - } - -#ifdef KEY_LISTENERS_DEBUG - size_t currsize = _keyListeners.size(); - log_msg("Cleaned up %u listeners (from %u to %u)", prevsize-currsize, prevsize, currsize); -#endif -} - -void movie_root::notify_key_listeners(key::code k, bool down) -{ - //log_msg("Notifying " SIZET_FMT " keypress listeners", _keyListeners.size()); - - for (KeyListeners::iterator iter = _keyListeners.begin(); - iter != _keyListeners.end(); ++iter) - { - boost::intrusive_ptr<as_object> obj = iter->get(); - character* ch = dynamic_cast<character*>(obj.get()); - // notify character listeners - if ( ch && ! ch->isUnloaded() ) - { - if(down) - { - // invoke onClipKeyDown handler - ch->on_event(event_id(event_id::KEY_DOWN, key::INVALID)); - - if(iter->hasUserRegistered()) - // invoke onKeyDown handler - { - VM& vm = VM::get(); - string_table& st =vm.getStringTable(); - ch->callMethod(st.find(PROPNAME("onKeyDown")), ch->get_environment()); - } - // invoke onClipKeyPress handler - ch->on_event(event_id(event_id::KEY_PRESS, key::codeMap[k][0])); - } - else - { - //invoke onClipKeyUp handler - ch->on_event(event_id(event_id::KEY_UP, key::INVALID)); - - if(iter->hasUserRegistered()) - // invoke onKeyUp handler - { - VM& vm = VM::get(); - string_table& st =vm.getStringTable(); - ch->callMethod(st.find(PROPNAME("onKeyUp")), ch->get_environment()); - } - } - } - // notify non-character listeners - else - { - if(down) - { - iter->get()->on_event(event_id(event_id::KEY_DOWN, key::INVALID)); - } - else - { - iter->get()->on_event(event_id(event_id::KEY_UP, key::INVALID)); - } - } - } - assert(testInvariant()); -} - -void movie_root::add_key_listener(const KeyListener & listener) -{ - KeyListeners::iterator target = _keyListeners.find(listener); - if(target == _keyListeners.end()) - // The key listener is not in the container, then add it. - { - _keyListeners.insert(listener); - } - else - // The key listener is already in the container, then register it(again). - { - if(listener.hasUserRegistered()) - { - target->registerUserHandler(); - } - if(listener.hasOnClipRegistered()) - { - target->registerOnClipHandler(); - } - } - - assert(testInvariant()); -} - -void movie_root::remove_key_listener(as_object* listener) -{ - _keyListeners.erase(KeyListener(listener)); - - assert(testInvariant()); -} - -#else // ndef NEW_KEY_LISTENER_LIST_DESIGN - void movie_root::cleanup_key_listeners() { -#ifdef KEY_LISTENERS_DEBUG - size_t prevsize = _keyListeners.size(); - log_msg("Cleaning up %u key listeners", _keyListeners.size()); -#endif - - for (ListenerSet::iterator iter = m_key_listeners.begin(); iter != m_key_listeners.end(); ) + // remove unloaded character listeners from movie_root + for (KeyListeners::iterator iter = m_key_listeners.begin(); iter != m_key_listeners.end(); ) { - // TODO: handle non-character objects too ! character* ch = dynamic_cast<character*>(iter->get()); if ( ch && ch->isUnloaded() ) { - ListenerSet::iterator toremove = iter; - ++iter; - //log_msg("cleanup_key_listeners: Removing unloaded key listener %p", iter->get()); - m_key_listeners.erase(toremove); + m_key_listeners.erase(iter++); } else { @@ -1044,22 +894,22 @@ } } -#ifdef KEY_LISTENERS_DEBUG - size_t currsize = _keyListeners.size(); - log_msg("Cleaned up %u listeners (from %u to %u)", prevsize-currsize, prevsize, currsize); -#endif + if( _keyobject ) + { + // remove unloaded character listeners from global Key object + _keyobject->cleanup_unloaded_listeners(); + } } void movie_root::notify_key_listeners(key::code k, bool down) { - log_msg("Notifying " SIZET_FMT " keypress listeners", - m_key_listeners.size()); + // log_msg("Notifying " SIZET_FMT " character listeners", + // m_key_listeners.size()); - for (ListenerSet::iterator iter = m_key_listeners.begin(); + for (KeyListeners::iterator iter = m_key_listeners.begin(); iter != m_key_listeners.end(); ++iter) { // sprite, button & input_edit_text characters - // TODO: invoke functions on non-characters ! character* ch = dynamic_cast<character*>(iter->get()); if ( ch && ! ch->isUnloaded() ) { @@ -1079,25 +929,33 @@ void movie_root::add_key_listener(as_object* listener) { - if ( m_key_listeners.insert(listener).second ) - { - //log_msg("Added key listener %p", (void*)listener); - } - else + for(KeyListeners::iterator i = m_key_listeners.begin(), e = m_key_listeners.end(); + i != e; ++i) { - //log_msg("key listener %p was already in the known set", (void*)listener); + // Conceptually, we don't need to add the same character twice. + // but see edit_text_character::setFocus()... + if(*i == listener) return; } - assert(testInvariant()); + + //for character listeners, first added last called + m_key_listeners.push_front(listener); } void movie_root::remove_key_listener(as_object* listener) { - //log_msg("Removing key listener %p - %u listeners currently ", (void*)listener, m_key_listeners.size()); - m_key_listeners.erase(listener); - //log_msg("After removing key listener %p, %u listeners are left", (void*)listener, m_key_listeners.size()); - assert(testInvariant()); + for(KeyListeners::iterator iter = m_key_listeners.begin(); + iter != m_key_listeners.end(); ) + { + if(*iter == listener) + { + m_key_listeners.erase(iter++); + } + else + { + iter++; + } + } } -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN void movie_root::add_mouse_listener(as_object* listener) { @@ -1394,21 +1252,12 @@ } } -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - // Mark key listeners - for (KeyListeners::const_iterator i=_keyListeners.begin(), e=_keyListeners.end(); - i != e; ++i) - { - i->setReachable(); - } -#else - // Mark key listeners - for (ListenerSet::const_iterator i=m_key_listeners.begin(), e=m_key_listeners.end(); + // Mark character key listeners + for (KeyListeners::const_iterator i=m_key_listeners.begin(), e=m_key_listeners.end(); i != e; ++i) { (*i)->setReachable(); } -#endif // Mark global key object if ( _keyobject ) _keyobject->setReachable(); Index: server/movie_root.h =================================================================== RCS file: /sources/gnash/gnash/server/movie_root.h,v retrieving revision 1.87 retrieving revision 1.88 diff -u -b -r1.87 -r1.88 --- server/movie_root.h 14 Nov 2007 13:23:47 -0000 1.87 +++ server/movie_root.h 16 Nov 2007 07:43:53 -0000 1.88 @@ -15,7 +15,7 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -/* $Id: movie_root.h,v 1.87 2007/11/14 13:23:47 strk Exp $ */ +/* $Id: movie_root.h,v 1.88 2007/11/16 07:43:53 zoulunkai Exp $ */ /// \page events_handling Handling of user events /// @@ -103,76 +103,6 @@ } }; -#ifdef NEW_KEY_LISTENER_LIST_DESIGN -class KeyListener{ - public: - - KeyListener(boost::intrusive_ptr<as_object> obj, int flag=0) - : _listener(obj), _registered_type(flag) - {} - - boost::intrusive_ptr<as_object> get() const { return _listener; } - - bool operator == (const KeyListener & rhs ) const { return _listener == rhs.get(); } - bool operator != (const KeyListener & rhs ) const { return _listener != rhs.get(); } - bool operator < (const KeyListener & rhs ) const { return _listener < rhs.get(); } - - enum - { - ON_CLIP_DEF = 1 << 0, - USER_DEF = 1 << 1 - }; - - /// \brief - /// true if the _listener has OnClip defined key event handlers, - /// false if the _listener has no OnClip defined key event handlers. - /// - /// OnClip defined key event handlers are registered automatically and can not - /// be unregistered when they are defined. - bool hasOnClipRegistered() const { return _registered_type & ON_CLIP_DEF; } - - /// \brief - /// true if the _listener has been registered by Key.addListener(), - /// false if the _listener has not been registered by Key.addListener() - /// or unregistered by Key.removeListener(). - bool hasUserRegistered() const { return _registered_type & USER_DEF; } - - /// register user defined key handler - void registerUserHandler() const { _registered_type |= USER_DEF; } - - /// register OnClip defined key handler - void registerOnClipHandler() const { _registered_type |= ON_CLIP_DEF; } - - /// unregister user defined key handler - void unregisterUserHandler() const { _registered_type ^= USER_DEF; } - -#ifdef GNASH_USE_GC - /// Mark the wrapped object as reachable - void setReachable() const - { - if ( _listener ) _listener->setReachable(); - } -#endif - - private: - - /// the listener object, could be a character or a general as_object - boost::intrusive_ptr<as_object> _listener; - - /// 0: the listener has no registered event handlers, to be removed; - /// ON_CLIP_DEF: the listener has registered onClip event handlers; - /// USER_DEF: the listener has registered user defined handlers; - // - // (1) onClip handlers get registered as soon as they are defined, and - // will never get unregistered; - // (2) user defined handlers get registered by Key.addListener(obj), - // and unregistered by Key.removedListener(obj); - // mutable here is a hack for using std::set<>, we might drop this class - // or change to another container later. - mutable int _registered_type; - }; -#endif - /// The movie stage (absolute top level node in the characters hierarchy) // /// This is a wrapper around the set of loaded levels being played. @@ -482,24 +412,19 @@ void * get_userdata() { return m_userdata; } void set_userdata(void * ud ) { m_userdata = ud; } + /// Notify both the character listeners and general object listeners DSOEXPORT void notify_key_listeners(key::code k, bool down); -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - // Push a new key listener to the container if it is not there, - // otherwise, just register it. - void add_key_listener(const KeyListener& listener); - // remove the specified listener from the container if found - void remove_key_listener(as_object* listener); - - typedef std::set<KeyListener> KeyListeners; - KeyListeners & getKeyListeners() { return _keyListeners; } -#else + /// Push a new character listener to the container after constructing the character void add_key_listener(as_object* listener); + + /// Remove a character from the container only when the character is unloaded void remove_key_listener(as_object* listener); -#endif DSOEXPORT void notify_mouse_listeners(const event_id& event); + void add_mouse_listener(as_object* listener); + void remove_mouse_listener(as_object* listener); /// Get the character having focus @@ -709,14 +634,14 @@ unsigned int _lastTimerId; /// A set of as_objects kept by intrusive_ptr + /// TODO: dont' use std::use, we need to well control the calling order typedef std::set< boost::intrusive_ptr<as_object> > ListenerSet; - /// Objects listening for key events -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - KeyListeners _keyListeners; -#else - ListenerSet m_key_listeners; -#endif + /// key listeners container + typedef std::list< boost::intrusive_ptr<as_object> > KeyListeners; + + /// Characters for listening key events + KeyListeners m_key_listeners; boost::intrusive_ptr<key_as_object> _keyobject; Index: server/sprite_instance.cpp =================================================================== RCS file: /sources/gnash/gnash/server/sprite_instance.cpp,v retrieving revision 1.387 retrieving revision 1.388 diff -u -b -r1.387 -r1.388 --- server/sprite_instance.cpp 15 Nov 2007 22:23:34 -0000 1.387 +++ server/sprite_instance.cpp 16 Nov 2007 07:43:53 -0000 1.388 @@ -3356,19 +3356,14 @@ method_name, method_arg_fmt, args); } +/// register characters as key listeners if they have clip key events defined. +/// Don't call twice for the same chracter. void sprite_instance::registerAsListener() { if (m_has_key_event) { -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - // TODO: Don't do this at every advancement - // OnClip key handlers should be registered at construction time, - // User defined handlers should be registered explicitly by Key.addListener(); - _vm.getRoot().add_key_listener(KeyListener(this, KeyListener::ON_CLIP_DEF)); -#else _vm.getRoot().add_key_listener(this); -#endif } // Mouse events listening is done in has_mouse_event directly. // This shows to work better for attachMovieTest.swf, Index: server/asobj/Key.cpp =================================================================== RCS file: /sources/gnash/gnash/server/asobj/Key.cpp,v retrieving revision 1.43 retrieving revision 1.44 diff -u -b -r1.43 -r1.44 --- server/asobj/Key.cpp 14 Nov 2007 05:12:51 -0000 1.43 +++ server/asobj/Key.cpp 16 Nov 2007 07:43:53 -0000 1.44 @@ -36,15 +36,15 @@ namespace gnash { /************************************************************************ - * - * This has been moved from action.cpp, when things are clean - * everything should have been moved up - * - ************************************************************************/ +* +* This has been moved from action.cpp, when things are clean +* everything should have been moved up +* +************************************************************************/ key_as_object::key_as_object() : - as_object(getObjectInterface()), +as_object(getObjectInterface()), m_last_key_event(0) { memset(m_unreleased_keys, 0, sizeof(m_unreleased_keys)); @@ -68,7 +68,7 @@ } void -key_as_object::set_key_down(int code) + key_as_object::set_key_down(int code) { if (code < 0 || code >= key::KEYCOUNT) return; @@ -108,73 +108,85 @@ m_unreleased_keys[byte_index] &= ~mask; } -#ifndef NEW_KEY_LISTENER_LIST_DESIGN + void -key_as_object::notify_listeners(const event_id key_event_type) +key_as_object::notify_listeners(const event_id key_event) { - - std::string funcname = key_event_type.get_function_name(); - // There is no user defined "onKeyPress" event handler - if( ( funcname != "onKeyDown") && (funcname != "onKeyUp") ) + if( m_listeners.empty() ) + { return; + } - VM& vm = VM::get(); - if ( vm.getSWFVersion() < 7 ) + std::string handler_name; + // There is no user defined "onKeyPress" event handler + if( (key_event.m_id == event_id::KEY_DOWN) || (key_event.m_id == event_id::KEY_UP) ) + { + handler_name = key_event.get_function_name(); + if ( _vm.getSWFVersion() < 7 ) + { + boost::to_lower(handler_name, _vm.getLocale()); + } + } + else { - boost::to_lower(funcname, vm.getLocale()); + return; } - // Notify listeners. - for (std::vector<boost::intrusive_ptr<as_object> >::iterator iter = m_listeners.begin(); - iter != m_listeners.end(); ++iter) { - if (*iter == NULL) - continue; + for (Listeners::iterator iter = m_listeners.begin(); iter != m_listeners.end(); ++iter) + { + if (*iter == NULL) continue; - boost::intrusive_ptr<as_object> listener = *iter; // Hold an owning reference. - as_value method; + as_value event_handler; + bool found_handler = + iter->get()->get_member(_vm.getStringTable().find(handler_name), &event_handler); - if (listener->get_member(VM::get().getStringTable().find(funcname), &method)) - call_method(method, NULL /* or root? */, listener.get(), 0, 0); + if(found_handler) + { + character* ch = dynamic_cast<character *>(iter->get()); + if(ch && !ch->isUnloaded()) + { + // execute character handlers + call_method(event_handler, &ch->get_environment(), ch, 0, 0); } -} -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN + else + { + // execute non-character handlers + call_method(event_handler, NULL, iter->get(), 0, 0); + } + } + } // end of for -#ifdef NEW_KEY_LISTENER_LIST_DESIGN -void -key_as_object::add_listener(const KeyListener& listener) -{ - _vm.getRoot().add_key_listener(listener); } + void -key_as_object::remove_listener(boost::intrusive_ptr<as_object> listener) +key_as_object::cleanup_unloaded_listeners() { - // Should keep consistent with definiton in movie_root.h - typedef std::set<KeyListener> KeyListeners; - - KeyListeners & listeners = _vm.getRoot().getKeyListeners(); - - KeyListeners::iterator target = listeners.find(KeyListener(listener)); - - KeyListeners::iterator it_end = listeners.end(); - - if(target != it_end) + for (Listeners::iterator iter = m_listeners.begin(); iter != m_listeners.end(); ) + { + boost::intrusive_ptr<character> ch = dynamic_cast<character *> (iter->get()); + if (ch && ch->isUnloaded()) + { + m_listeners.erase(iter++); + continue; + } + else { - target->unregisterUserHandler(); + ++iter; + } } } -#else // ndef NEW_KEY_LISTENER_LIST_DESIGN void key_as_object::add_listener(boost::intrusive_ptr<as_object> listener) { // Should we bother doing this every time someone calls add_listener(), // or should we perhaps skip this check and use unique later? - std::vector<boost::intrusive_ptr<as_object> >::const_iterator end = m_listeners.end(); - for (std::vector<boost::intrusive_ptr<as_object> >::iterator iter = m_listeners.begin(); - iter != end; ++iter) { - if (*iter == NULL) { + for (Listeners::iterator i = m_listeners.begin(), e = m_listeners.end(); i != e; ++i) + { + if (*i == listener) + { // Already in the list. return; } @@ -183,21 +195,22 @@ m_listeners.push_back(listener); } + void key_as_object::remove_listener(boost::intrusive_ptr<as_object> listener) { - for (std::vector<boost::intrusive_ptr<as_object> >::iterator iter = m_listeners.begin(); iter != m_listeners.end(); ) + for (Listeners::iterator iter = m_listeners.begin(); iter != m_listeners.end(); ) { if (*iter == listener) { - iter = m_listeners.erase(iter); + m_listeners.erase(iter++); continue; } iter++; } } -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN + int key_as_object::get_last_key() const @@ -229,22 +242,13 @@ return as_value(); } -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - - ko->add_listener(KeyListener(toadd, KeyListener::USER_DEF)); - -#else // ndef NEW_KEY_LISTENER_LIST_DESIGN - ko->add_listener(toadd); -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN - return as_value(); } -// Return the ascii value of the last key pressed. -/// FIXME: return the ascii number(not string) of the last pressed key! +/// Return the ascii number of the last key pressed. static as_value key_get_ascii(const fn_call& fn) { @@ -255,9 +259,9 @@ return as_value(gnash::key::codeMap[code][2]); } -// Returns the keycode of the last key pressed. +/// Returns the keycode of the last key pressed. static as_value -key_get_code(const fn_call& fn) + key_get_code(const fn_call& fn) { boost::intrusive_ptr<key_as_object> ko = ensureType<key_as_object>(fn.this_ptr); @@ -329,8 +333,8 @@ void key_class_init(as_object& global) { -// GNASH_REPORT_FUNCTION; -// + // GNASH_REPORT_FUNCTION; + // int swfversion = VM::get().getSWFVersion(); // Create built-in key object. @@ -375,7 +379,6 @@ } #ifdef GNASH_USE_GC -#ifndef NEW_KEY_LISTENER_LIST_DESIGN void key_as_object::markReachableResources() const { @@ -386,7 +389,6 @@ (*i)->setReachable(); } } -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN #endif // def GNASH_USE_GC } // end of gnash namespace Index: server/asobj/Key.h =================================================================== RCS file: /sources/gnash/gnash/server/asobj/Key.h,v retrieving revision 1.29 retrieving revision 1.30 diff -u -b -r1.29 -r1.30 --- server/asobj/Key.h 10 Oct 2007 14:07:58 -0000 1.29 +++ server/asobj/Key.h 16 Nov 2007 07:43:53 -0000 1.30 @@ -16,7 +16,7 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // -/* $Id: Key.h,v 1.29 2007/10/10 14:07:58 bwy Exp $ */ +/* $Id: Key.h,v 1.30 2007/11/16 07:43:53 zoulunkai Exp $ */ #ifndef __KEY_H__ #define __KEY_H__ @@ -39,10 +39,6 @@ namespace gnash { -#ifdef NEW_KEY_LISTENER_LIST_DESIGN -class KeyListener; //forward declaration -#endif - /************************************************************************ * * This has been moved from action.cpp, when things are clean @@ -57,22 +53,16 @@ /// bit-array for recording the unreleased keys uint8_t m_unreleased_keys[key::KEYCOUNT / 8 + 1]; -#ifndef NEW_KEY_LISTENER_LIST_DESIGN - typedef std::vector<boost::intrusive_ptr<as_object> > Listeners; + typedef std::list<boost::intrusive_ptr<as_object> > Listeners; Listeners m_listeners; -#endif int m_last_key_event; protected: #ifdef GNASH_USE_GC -#ifndef NEW_KEY_LISTENER_LIST_DESIGN // Mark all key listeners as reachable - // (this class has no direct pointer to listeners when - // NEW_KEY_LISTENER_LIST_DESIGN is defined) void markReachableResources() const; -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN #endif // def GNASH_USE_GC public: @@ -92,24 +82,18 @@ // pressed (m_unreleased_keys) void set_key_up(int code); -#ifndef NEW_KEY_LISTENER_LIST_DESIGN - /// responsible for user defined key events handlers only; + int get_last_key() const; + + /// Responsible for user defined key events handlers only; /// take over both characters and non-characters object. void notify_listeners(const event_id key_event_type); -#endif // ndef NEW_KEY_LISTENER_LIST_DESIGN -#ifdef NEW_KEY_LISTENER_LIST_DESIGN - void add_listener(const KeyListener& listener); + /// Remove unloaded character listeners from the list. + void cleanup_unloaded_listeners(); - void remove_listener(boost::intrusive_ptr<as_object> listener); -#else void add_listener(boost::intrusive_ptr<as_object> listener); void remove_listener(boost::intrusive_ptr<as_object> listener); -#endif - - int get_last_key() const; - }; void key_class_init(as_object& global); Index: testsuite/misc-ming.all/key_event_test.c =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/key_event_test.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -b -r1.6 -r1.7 --- testsuite/misc-ming.all/key_event_test.c 15 Nov 2007 08:39:27 -0000 1.6 +++ testsuite/misc-ming.all/key_event_test.c 16 Nov 2007 07:43:53 -0000 1.7 @@ -291,7 +291,7 @@ SWFDisplayItem_remove(it3); SWFMovie_nextFrame(mo); // _root frame22 - xcheck_equals(mo, "test5", "'0+ls3+ls2+ls1+obj1+ls1+obj2+ls2+obj3+obj1+obj2+obj3'"); + check_equals(mo, "test5", "'0+ls3+ls2+ls1+obj1+ls1+obj2+ls2+obj3+obj1+obj2+obj3'"); add_actions(mo, "totals(); stop();"); SWFMovie_nextFrame(mo); // _root frame23 //Output movie Index: testsuite/misc-ming.all/key_event_testrunner.cpp =================================================================== RCS file: /sources/gnash/gnash/testsuite/misc-ming.all/key_event_testrunner.cpp,v retrieving revision 1.14 retrieving revision 1.15 diff -u -b -r1.14 -r1.15 --- testsuite/misc-ming.all/key_event_testrunner.cpp 15 Nov 2007 08:51:57 -0000 1.14 +++ testsuite/misc-ming.all/key_event_testrunner.cpp 16 Nov 2007 07:43:53 -0000 1.15 @@ -125,8 +125,7 @@ tester.releaseKey(key::F); // we have jumped backward to frame11 - // Gnash failed on notifying an unloaded character listener - xcheck_equals(root->get_current_frame(), 10); + check_equals(root->get_current_frame(), 10); tester.advance(); // and we are in frame12 again _______________________________________________ Gnash-commit mailing list Gnash-commit@gnu.org http://lists.gnu.org/mailman/listinfo/gnash-commit