From: <m97...@us...> - 2008-09-18 10:55:44
|
Revision: 8239 http://openmsx.svn.sourceforge.net/openmsx/?rev=8239&view=rev Author: m9710797 Date: 2008-09-18 17:55:55 +0000 (Thu, 18 Sep 2008) Log Message: ----------- Store old value of machine specific update events in MSXCliComm instead of GlobalCliComm To avoid sending too much data over clicomm connections, we remember the last value of an update event and only send the event if the new value is different. Before this commit this was handled in one place (GlobalCliComm) for both global and machine specific update events. This commit duplicates this filter mechanism in both GlobalCliComm (now only global) and MSXCliComm (only machine specific). The advantage is that when a machine is deleted, the data about the machine specific events now also disappears. Before this data was kept forever (about 5kb per machine). This is a memory leak, but not one detectable by tools like valgrind (because the memory is properly freed when openmsx exits). Modified Paths: -------------- openmsx/trunk/src/events/GlobalCliComm.cc openmsx/trunk/src/events/GlobalCliComm.hh openmsx/trunk/src/events/MSXCliComm.cc openmsx/trunk/src/events/MSXCliComm.hh Modified: openmsx/trunk/src/events/GlobalCliComm.cc =================================================================== --- openmsx/trunk/src/events/GlobalCliComm.cc 2008-09-18 17:55:34 UTC (rev 8238) +++ openmsx/trunk/src/events/GlobalCliComm.cc 2008-09-18 17:55:55 UTC (rev 8239) @@ -127,22 +127,22 @@ void GlobalCliComm::update(UpdateType type, const string& name, const string& value) { - update(type, "", name, value); -} - -void GlobalCliComm::update(UpdateType type, const string& machine, - const string& name, const string& value) -{ assert(type < NUM_UPDATES); - map<string, string>::iterator it = prevValues[type][machine].find(name); - if (it != prevValues[type][machine].end()) { + map<string, string>::iterator it = prevValues[type].find(name); + if (it != prevValues[type].end()) { if (it->second == value) { return; } it->second = value; } else { - prevValues[type][machine][name] = value; + prevValues[type][name] = value; } + updateHelper(type, "", name, value); +} + +void GlobalCliComm::updateHelper(UpdateType type, const string& machine, + const string& name, const string& value) +{ ScopedLock lock(sem); if (!connections.empty()) { string str = string("<update type=\"") + updateStr[type] + '\"'; Modified: openmsx/trunk/src/events/GlobalCliComm.hh =================================================================== --- openmsx/trunk/src/events/GlobalCliComm.hh 2008-09-18 17:55:34 UTC (rev 8238) +++ openmsx/trunk/src/events/GlobalCliComm.hh 2008-09-18 17:55:55 UTC (rev 8239) @@ -34,13 +34,12 @@ const std::string& value); private: - void update(UpdateType type, const std::string& machine, - const std::string& name, const std::string& value); + void updateHelper(UpdateType type, const std::string& machine, + const std::string& name, const std::string& value); const std::auto_ptr<UpdateCmd> updateCmd; - std::map<std::string, std::map<std::string, std::string> > - prevValues[NUM_UPDATES]; + std::map<std::string, std::string> prevValues[NUM_UPDATES]; GlobalCommandController& commandController; EventDistributor& eventDistributor; Modified: openmsx/trunk/src/events/MSXCliComm.cc =================================================================== --- openmsx/trunk/src/events/MSXCliComm.cc 2008-09-18 17:55:34 UTC (rev 8238) +++ openmsx/trunk/src/events/MSXCliComm.cc 2008-09-18 17:55:55 UTC (rev 8239) @@ -4,6 +4,7 @@ #include "GlobalCliComm.hh" #include "MSXMotherBoard.hh" +using std::map; using std::string; namespace openmsx { @@ -22,7 +23,17 @@ void MSXCliComm::update(UpdateType type, const string& name, const string& value) { - cliComm.update(type, motherBoard.getMachineID(), name, value); + assert(type < NUM_UPDATES); + map<string, string>::iterator it = prevValues[type].find(name); + if (it != prevValues[type].end()) { + if (it->second == value) { + return; + } + it->second = value; + } else { + prevValues[type][name] = value; + } + cliComm.updateHelper(type, motherBoard.getMachineID(), name, value); } } // namespace openmsx Modified: openmsx/trunk/src/events/MSXCliComm.hh =================================================================== --- openmsx/trunk/src/events/MSXCliComm.hh 2008-09-18 17:55:34 UTC (rev 8238) +++ openmsx/trunk/src/events/MSXCliComm.hh 2008-09-18 17:55:55 UTC (rev 8239) @@ -5,6 +5,7 @@ #include "CliComm.hh" #include "noncopyable.hh" +#include <map> namespace openmsx { @@ -23,6 +24,8 @@ private: MSXMotherBoard& motherBoard; GlobalCliComm& cliComm; + + std::map<std::string, std::string> prevValues[NUM_UPDATES]; }; } // namespace openmsx This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2009-03-30 16:55:55
|
Revision: 9440 http://openmsx.svn.sourceforge.net/openmsx/?rev=9440&view=rev Author: m9710797 Date: 2009-03-30 16:55:41 +0000 (Mon, 30 Mar 2009) Log Message: ----------- Fixed crash when when an after command tried to cancel itself Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/AfterCommand.hh Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2009-03-29 22:46:23 UTC (rev 9439) +++ openmsx/trunk/src/events/AfterCommand.cc 2009-03-30 16:55:41 UTC (rev 9440) @@ -5,13 +5,13 @@ #include "CliComm.hh" #include "Schedulable.hh" #include "EventDistributor.hh" -#include "Event.hh" #include "Reactor.hh" #include "MSXMotherBoard.hh" #include "Alarm.hh" #include "EmuTime.hh" #include "CommandException.hh" #include "openmsx.hh" +#include <algorithm> #include <cstdlib> #include <sstream> @@ -33,6 +33,7 @@ protected: AfterCmd(AfterCommand& afterCommand, const std::string& command); + shared_ptr<AfterCmd> removeSelf(); private: AfterCommand& afterCommand; std::string command; @@ -144,10 +145,6 @@ AfterCommand::~AfterCommand() { - while (!afterCmds.empty()) { - delete afterCmds.begin()->second; // removes itself from map - } - eventDistributor.unregisterEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); eventDistributor.unregisterEventListener( @@ -176,16 +173,6 @@ OPENMSX_KEY_UP_EVENT, *this); } -template<EventType T> -static string afterEvent(const vector<string>& tokens, AfterCommand& after) -{ - if (tokens.size() != 3) { - throw SyntaxError(); - } - AfterEventCmd<T>* cmd = new AfterEventCmd<T>(after, tokens[1], tokens[2]); - return cmd->getId(); -} - string AfterCommand::execute(const vector<string>& tokens) { if (tokens.size() < 2) { @@ -198,13 +185,13 @@ } else if (tokens[1] == "idle") { return afterIdle(tokens); } else if (tokens[1] == "frame") { - return afterEvent<OPENMSX_FINISH_FRAME_EVENT>(tokens, *this); + return afterEvent<OPENMSX_FINISH_FRAME_EVENT>(tokens); } else if (tokens[1] == "break") { - return afterEvent<OPENMSX_BREAK_EVENT>(tokens, *this); + return afterEvent<OPENMSX_BREAK_EVENT>(tokens); } else if (tokens[1] == "boot") { - return afterEvent<OPENMSX_BOOT_EVENT>(tokens, *this); + return afterEvent<OPENMSX_BOOT_EVENT>(tokens); } else if (tokens[1] == "machine_switch") { - return afterEvent<OPENMSX_MACHINE_LOADED_EVENT>(tokens, *this); + return afterEvent<OPENMSX_MACHINE_LOADED_EVENT>(tokens); } else if (tokens[1] == "info") { return afterInfo(tokens); } else if (tokens[1] == "cancel") { @@ -235,8 +222,9 @@ return ""; } double time = getTime(tokens[2]); - AfterTimeCmd* cmd = new AfterTimeCmd( - motherBoard->getScheduler(), *this, tokens[3], time); + shared_ptr<AfterCmd> cmd(new AfterTimeCmd( + motherBoard->getScheduler(), *this, tokens[3], time)); + afterCmds.push_back(cmd); return cmd->getId(); } @@ -246,11 +234,23 @@ throw SyntaxError(); } double time = getTime(tokens[2]); - AfterRealTimeCmd* cmd = new AfterRealTimeCmd( - *this, eventDistributor, tokens[3], time); + shared_ptr<AfterCmd> cmd(new AfterRealTimeCmd( + *this, eventDistributor, tokens[3], time)); + afterCmds.push_back(cmd); return cmd->getId(); } +template<EventType T> +string AfterCommand::afterEvent(const vector<string>& tokens) +{ + if (tokens.size() != 3) { + throw SyntaxError(); + } + shared_ptr<AfterCmd> cmd(new AfterEventCmd<T>(*this, tokens[1], tokens[2])); + afterCmds.push_back(cmd); + return cmd->getId(); +} + string AfterCommand::afterIdle(const vector<string>& tokens) { if (tokens.size() != 4) { @@ -261,17 +261,18 @@ return ""; } double time = getTime(tokens[2]); - AfterIdleCmd* cmd = new AfterIdleCmd( - motherBoard->getScheduler(), *this, tokens[3], time); + shared_ptr<AfterCmd> cmd(new AfterIdleCmd( + motherBoard->getScheduler(), *this, tokens[3], time)); + afterCmds.push_back(cmd); return cmd->getId(); } string AfterCommand::afterInfo(const vector<string>& /*tokens*/) { string result; - for (AfterCmdMap::const_iterator it = afterCmds.begin(); + for (AfterCmds::const_iterator it = afterCmds.begin(); it != afterCmds.end(); ++it) { - const AfterCmd* cmd = it->second; + const AfterCmd* cmd = it->get(); ostringstream str; str << cmd->getId() << ": "; str << cmd->getType() << ' '; @@ -291,11 +292,16 @@ if (tokens.size() != 3) { throw SyntaxError(); } - AfterCmdMap::iterator it = afterCmds.find(tokens[2]); + AfterCmds::iterator it = afterCmds.begin(); + for (/**/; it != afterCmds.end(); ++it) { + if ((*it)->getId() == tokens[2]) { + break; + } + } if (it == afterCmds.end()) { throw CommandException("No delayed command with this id"); } - delete it->second; + afterCmds.erase(it); return ""; } @@ -328,36 +334,43 @@ // TODO : make more complete } -template<EventType T> static void executeEvents( - const AfterCommand::AfterCmdMap& afterCmds) + +template<EventType T> struct AfterEventPred { + bool operator()(shared_ptr<AfterCmd> x) const { + return !dynamic_cast<AfterEventCmd<T>*>(x.get()); + } +}; +template<EventType T> void AfterCommand::executeEvents() { - vector<AfterCmd*> tmp; // make copy because map will change - for (AfterCommand::AfterCmdMap::const_iterator it = afterCmds.begin(); - it != afterCmds.end(); ++it) { - if (dynamic_cast<AfterEventCmd<T>*>(it->second)) { - tmp.push_back(it->second); - } - } - for (vector<AfterCmd*>::iterator it = tmp.begin(); - it != tmp.end(); ++it) { + AfterCmds::iterator it = partition(afterCmds.begin(), afterCmds.end(), + AfterEventPred<T>()); + AfterCmds tmp(it, afterCmds.end()); + afterCmds.erase(it, afterCmds.end()); + + for (AfterCmds::iterator it = tmp.begin(); it != tmp.end(); ++it) { (*it)->execute(); } } -void AfterCommand::executeRealTime() -{ - vector<AfterCmd*> tmp; // make copy because map will change - for (AfterCmdMap::const_iterator it = afterCmds.begin(); - it != afterCmds.end(); ++it) { +struct AfterTimePred { + bool operator()(shared_ptr<AfterCmd> x) const { if (AfterRealTimeCmd* realtimeCmd = - dynamic_cast<AfterRealTimeCmd*>(it->second)) { + dynamic_cast<AfterRealTimeCmd*>(x.get())) { if (realtimeCmd->hasExpired()) { - tmp.push_back(it->second); + return false; } } + return true; } - for (vector<AfterCmd*>::iterator it = tmp.begin(); - it != tmp.end(); ++it) { +}; +void AfterCommand::executeRealTime() +{ + AfterCmds::iterator it = partition(afterCmds.begin(), afterCmds.end(), + AfterTimePred()); + AfterCmds tmp(it, afterCmds.end()); + afterCmds.erase(it, afterCmds.end()); + + for (AfterCmds::iterator it = tmp.begin(); it != tmp.end(); ++it) { (*it)->execute(); } } @@ -365,20 +378,21 @@ bool AfterCommand::signalEvent(shared_ptr<const Event> event) { if (event->getType() == OPENMSX_FINISH_FRAME_EVENT) { - executeEvents<OPENMSX_FINISH_FRAME_EVENT>(afterCmds); + executeEvents<OPENMSX_FINISH_FRAME_EVENT>(); } else if (event->getType() == OPENMSX_BREAK_EVENT) { - executeEvents<OPENMSX_BREAK_EVENT>(afterCmds); + executeEvents<OPENMSX_BREAK_EVENT>(); } else if (event->getType() == OPENMSX_BOOT_EVENT) { - executeEvents<OPENMSX_BOOT_EVENT>(afterCmds); + executeEvents<OPENMSX_BOOT_EVENT>(); } else if (event->getType() == OPENMSX_MACHINE_LOADED_EVENT) { - executeEvents<OPENMSX_MACHINE_LOADED_EVENT>(afterCmds); + executeEvents<OPENMSX_MACHINE_LOADED_EVENT>(); } else if (event->getType() == OPENMSX_AFTER_REALTIME_EVENT) { executeRealTime(); } else { - for (AfterCmdMap::const_iterator it = afterCmds.begin(); + for (AfterCmds::const_iterator it = afterCmds.begin(); it != afterCmds.end(); ++it) { - if (dynamic_cast<AfterIdleCmd*>(it->second)) { - static_cast<AfterIdleCmd*>(it->second)->reschedule(); + if (AfterIdleCmd* idleCmd = + dynamic_cast<AfterIdleCmd*>(it->get())) { + idleCmd->reschedule(); } } } @@ -390,20 +404,16 @@ unsigned AfterCmd::lastAfterId = 0; -AfterCmd::AfterCmd(AfterCommand& afterCommand_, - const string& command_) +AfterCmd::AfterCmd(AfterCommand& afterCommand_, const string& command_) : afterCommand(afterCommand_), command(command_) { ostringstream str; str << "after#" << ++lastAfterId; id = str.str(); - - afterCommand.afterCmds[id] = this; } AfterCmd::~AfterCmd() { - afterCommand.afterCmds.erase(id); } const string& AfterCmd::getCommand() const @@ -424,10 +434,23 @@ afterCommand.getCommandController().getCliComm().printWarning( "Error executing delayed command: " + e.getMessage()); } - delete this; } +shared_ptr<AfterCmd> AfterCmd::removeSelf() +{ + for (AfterCommand::AfterCmds::iterator it = afterCommand.afterCmds.begin(); + it != afterCommand.afterCmds.end(); ++it) { + if (it->get() == this) { + shared_ptr<AfterCmd> result = *it; + afterCommand.afterCmds.erase(it); + return result; + } + } + assert(false); + return shared_ptr<AfterCmd>(0); +} + // class AfterTimedCmd AfterTimedCmd::AfterTimedCmd( @@ -456,14 +479,13 @@ void AfterTimedCmd::executeUntil(EmuTime::param /*time*/, int /*userData*/) { - PRT_DEBUG("Going to execute after command...."); + shared_ptr<AfterCmd> self = removeSelf(); execute(); - PRT_DEBUG("Going to execute after command.... DONE!"); } void AfterTimedCmd::schedulerDeleted() { - delete this; + removeSelf(); } const string& AfterTimedCmd::schedName() const @@ -549,14 +571,11 @@ bool AfterRealTimeCmd::alarm() { - PRT_DEBUG("AfterRealTimeCmd::alarm()..."); // this runs in a different thread, so we can't directly execute the // command here expired = true; - PRT_DEBUG("AfterRealTimeCmd::alarm()... distribute AFTER REALTIME EVENT"); eventDistributor.distributeEvent( new SimpleEvent<OPENMSX_AFTER_REALTIME_EVENT>()); - PRT_DEBUG("AfterRealTimeCmd::alarm()... distribute AFTER REALTIME EVENT, DONE! Don't repeat."); return false; // don't repeat alarm } Modified: openmsx/trunk/src/events/AfterCommand.hh =================================================================== --- openmsx/trunk/src/events/AfterCommand.hh 2009-03-29 22:46:23 UTC (rev 9439) +++ openmsx/trunk/src/events/AfterCommand.hh 2009-03-30 16:55:41 UTC (rev 9440) @@ -5,7 +5,8 @@ #include "Command.hh" #include "EventListener.hh" -#include <map> +#include "Event.hh" +#include <vector> namespace openmsx { @@ -18,8 +19,6 @@ class AfterCommand : public SimpleCommand, private EventListener { public: - typedef std::map<std::string, AfterCmd*> AfterCmdMap; - AfterCommand(Reactor& reactor, EventDistributor& eventDistributor, CommandController& commandController); @@ -30,6 +29,9 @@ virtual void tabCompletion(std::vector<std::string>& tokens) const; private: + template<EventType T> void executeEvents(); + template<EventType T> std::string afterEvent( + const std::vector<std::string>& tokens); std::string afterTime(const std::vector<std::string>& tokens); std::string afterRealTime(const std::vector<std::string>& tokens); std::string afterIdle(const std::vector<std::string>& tokens); @@ -40,7 +42,8 @@ // EventListener virtual bool signalEvent(shared_ptr<const Event> event); - AfterCmdMap afterCmds; + typedef std::vector<shared_ptr<AfterCmd> > AfterCmds; + AfterCmds afterCmds; Reactor& reactor; EventDistributor& eventDistributor; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mfe...@us...> - 2009-04-05 21:01:15
|
Revision: 9480 http://openmsx.svn.sourceforge.net/openmsx/?rev=9480&view=rev Author: mfeingol Date: 2009-04-05 21:01:13 +0000 (Sun, 05 Apr 2009) Log Message: ----------- Another pass at the CliConnection issues to make both Catapult and the debugger work Modified Paths: -------------- openmsx/trunk/src/events/CliConnection.cc openmsx/trunk/src/events/CliConnection.hh Modified: openmsx/trunk/src/events/CliConnection.cc =================================================================== --- openmsx/trunk/src/events/CliConnection.cc 2009-04-05 16:53:16 UTC (rev 9479) +++ openmsx/trunk/src/events/CliConnection.cc 2009-04-05 21:01:13 UTC (rev 9480) @@ -94,22 +94,30 @@ return updateEnabled[type]; } +void CliConnection::startOutput() +{ + output("<openmsx-output>\n"); +} + +void CliConnection::endOutput() +{ + output("</openmsx-output>\n"); +} + void CliConnection::start() { + beforeConnection(); thread.start(); } void CliConnection::run() { - if (beforeConnection()) { - output("<openmsx-output>\n"); - connection(); - } + connection(); } void CliConnection::end() { - output("</openmsx-output>\n"); + endOutput(); close(); } @@ -219,9 +227,9 @@ end(); } -bool StdioConnection::beforeConnection() +void StdioConnection::beforeConnection() { - return true; + startOutput(); } void StdioConnection::connection() @@ -282,9 +290,12 @@ end(); } -bool PipeConnection::beforeConnection() +void PipeConnection::beforeConnection() { - return true; + // Emit the output element on this thread... + // Otherwise, this thread's startup actions will race with the + // connection thread. + startOutput(); } void PipeConnection::connection() @@ -335,21 +346,24 @@ end(); } -bool SocketConnection::beforeConnection() +void SocketConnection::beforeConnection() { + // We're on the accept thread, which we don't want to block +} + +void SocketConnection::connection() +{ #ifdef _WIN32 // Authenticate and authorize the caller SocketStreamWrapper stream(sd); SspiNegotiateServer server(stream); if (!server.Authenticate() || !server.Authorize()) { - return false; + return; } #endif - return true; -} + // Start output element + startOutput(); -void SocketConnection::connection() -{ // TODO is locking correct? // No need to lock in this thread because we don't write to 'sd' // and 'sd' only gets written to in this thread. Modified: openmsx/trunk/src/events/CliConnection.hh =================================================================== --- openmsx/trunk/src/events/CliConnection.hh 2009-04-05 16:53:16 UTC (rev 9479) +++ openmsx/trunk/src/events/CliConnection.hh 2009-04-05 21:01:13 UTC (rev 9480) @@ -44,10 +44,13 @@ void run(); - virtual bool beforeConnection() = 0; + virtual void beforeConnection() = 0; virtual void connection() = 0; virtual void close() = 0; + void startOutput(); + void endOutput(); + xmlParserCtxt* parser_context; Thread thread; // TODO: Possible to make this private? @@ -92,7 +95,7 @@ private: virtual void close(); - virtual bool beforeConnection(); + virtual void beforeConnection(); virtual void connection(); bool ok; @@ -111,7 +114,7 @@ private: virtual void close(); - virtual bool beforeConnection(); + virtual void beforeConnection(); virtual void connection(); HANDLE pipeHandle; @@ -130,7 +133,7 @@ private: virtual void close(); - virtual bool beforeConnection(); + virtual void beforeConnection(); virtual void connection(); Semaphore sem; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2009-04-26 21:30:58
|
Revision: 9633 http://openmsx.svn.sourceforge.net/openmsx/?rev=9633&view=rev Author: m9710797 Date: 2009-04-26 21:30:54 +0000 (Sun, 26 Apr 2009) Log Message: ----------- wip Modified Paths: -------------- openmsx/trunk/src/events/CliConnection.cc openmsx/trunk/src/events/CliConnection.hh Modified: openmsx/trunk/src/events/CliConnection.cc =================================================================== --- openmsx/trunk/src/events/CliConnection.cc 2009-04-26 21:20:50 UTC (rev 9632) +++ openmsx/trunk/src/events/CliConnection.cc 2009-04-26 21:30:54 UTC (rev 9633) @@ -99,25 +99,14 @@ output("<openmsx-output>\n"); } -void CliConnection::endOutput() -{ - output("</openmsx-output>\n"); -} - void CliConnection::start() { - beforeConnection(); thread.start(); } -void CliConnection::run() -{ - connection(); -} - void CliConnection::end() { - endOutput(); + output("</openmsx-output>\n"); close(); } @@ -219,6 +208,7 @@ : CliConnection(commandController, eventDistributor) , ok(true) { + startOutput(); start(); } @@ -227,13 +217,9 @@ end(); } -void StdioConnection::beforeConnection() +void StdioConnection::run() { - startOutput(); -} - -void StdioConnection::connection() -{ + // runs in helper thread while (ok) { char buf[BUF_SIZE]; int n = read(STDIN_FILENO, buf, sizeof(buf)); @@ -282,6 +268,7 @@ throw FatalError(msg); } + startOutput(); start(); } @@ -290,16 +277,9 @@ end(); } -void PipeConnection::beforeConnection() +void PipeConnection::run() { - // Emit the output element on this thread... - // Otherwise, this thread's startup actions will race with the - // connection thread. - startOutput(); -} - -void PipeConnection::connection() -{ + // runs in helper thread while (pipeHandle != OPENMSX_INVALID_HANDLE_VALUE) { char buf[BUF_SIZE]; unsigned long bytesRead; @@ -336,7 +316,7 @@ EventDistributor& eventDistributor, SOCKET sd_) : CliConnection(commandController, eventDistributor) - , sem(1), sd(sd_) + , sem(1), sd(sd_), established(false) { start(); } @@ -346,23 +326,25 @@ end(); } -void SocketConnection::beforeConnection() +void SocketConnection::run() { - // We're on the accept thread, which we don't want to block -} - -void SocketConnection::connection() -{ + // runs in helper thread #ifdef _WIN32 - // Authenticate and authorize the caller - SocketStreamWrapper stream(sd); - SspiNegotiateServer server(stream); - if (!server.Authenticate() || !server.Authorize()) { + { + ScopedLock lock(sem); + // Authenticate and authorize the caller + SocketStreamWrapper stream(sd); + SspiNegotiateServer server(stream); + bool ok = server.Authenticate() && server.Authorize(); + } + if (!ok) { + close(); return; } #endif // Start output element startOutput(); + established = true; // TODO needs locking? // TODO is locking correct? // No need to lock in this thread because we don't write to 'sd' @@ -382,6 +364,11 @@ void SocketConnection::output(const std::string& message) { + if (!established) { // TODO needs locking? + // Connection isn't authorized yet (and opening tag is not + // yet send). Ignore log and update messages for now. + return; + } const char* data = message.data(); unsigned pos = 0; size_t bytesLeft = message.size(); Modified: openmsx/trunk/src/events/CliConnection.hh =================================================================== --- openmsx/trunk/src/events/CliConnection.hh 2009-04-26 21:20:50 UTC (rev 9632) +++ openmsx/trunk/src/events/CliConnection.hh 2009-04-26 21:30:54 UTC (rev 9633) @@ -30,9 +30,9 @@ CliConnection(CommandController& commandController, EventDistributor& eventDistributor); - /** Starts this connection by writing the opening tag - * and starting the listener thread. + /** Starts the helper thread. * Subclasses should call this method at the end of their constructor. + * Subclasses should themself send the opening tag (startOutput()). */ void start(); @@ -42,14 +42,17 @@ */ void end(); - void run(); - - virtual void beforeConnection() = 0; - virtual void connection() = 0; + /** Close the connection. After this method is called, calls to + * output() should be ignored. + */ virtual void close() = 0; + /** Send opening XML tag, should be called exactly once by a subclass + * shortly after opening a connection. Cannot be implemented in the + * base class because some subclasses (want to send data before this + * tag). + */ void startOutput(); - void endOutput(); xmlParserCtxt* parser_context; Thread thread; // TODO: Possible to make this private? @@ -95,8 +98,7 @@ private: virtual void close(); - virtual void beforeConnection(); - virtual void connection(); + virtual void run(); bool ok; }; @@ -114,8 +116,7 @@ private: virtual void close(); - virtual void beforeConnection(); - virtual void connection(); + virtual void run(); HANDLE pipeHandle; }; @@ -133,11 +134,11 @@ private: virtual void close(); - virtual void beforeConnection(); - virtual void connection(); + virtual void run(); Semaphore sem; SOCKET sd; + bool established; }; } // namespace openmsx This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mth...@us...> - 2009-06-11 01:03:39
|
Revision: 10019 http://openmsx.svn.sourceforge.net/openmsx/?rev=10019&view=rev Author: mthuurne Date: 2009-06-11 00:32:59 +0000 (Thu, 11 Jun 2009) Log Message: ----------- Use SAX2 callbacks to parse XML. Otherwise it only works when libxml2 is compiled with SAX1 support, which is optional and no longer enabled in our 3rdparty build. Modified Paths: -------------- openmsx/trunk/src/events/CliConnection.cc openmsx/trunk/src/events/CliConnection.hh Modified: openmsx/trunk/src/events/CliConnection.cc =================================================================== --- openmsx/trunk/src/events/CliConnection.cc 2009-06-10 01:27:05 UTC (rev 10018) +++ openmsx/trunk/src/events/CliConnection.cc 2009-06-11 00:32:59 UTC (rev 10019) @@ -66,9 +66,10 @@ user_data.unknownLevel = 0; user_data.object = this; memset(&sax_handler, 0, sizeof(sax_handler)); - sax_handler.startElement = cb_start_element; - sax_handler.endElement = cb_end_element; - sax_handler.characters = cb_text; + sax_handler.startElementNs = cb_start_element; + sax_handler.endElementNs = cb_end_element; + sax_handler.characters = cb_text; + sax_handler.initialized = XML_SAX2_MAGIC; parser_context = xmlCreatePushParserCtxt(&sax_handler, &user_data, 0, 0, 0); @@ -141,8 +142,12 @@ return true; } -void CliConnection::cb_start_element(void* user_data, - const xmlChar* name, const xmlChar** /*attrs*/) +void CliConnection::cb_start_element( + void* user_data, + const xmlChar* localname, const xmlChar* /*prefix*/, const xmlChar* /*uri*/, + int /*nb_namespaces*/, const xmlChar** /*namespaces*/, + int /*nb_attributes*/, int /*nb_defaulted*/, const xmlChar** /*attrs*/ + ) { ParseState* parseState = static_cast<ParseState*>(user_data); if (parseState->unknownLevel) { @@ -151,14 +156,16 @@ } switch (parseState->state) { case START: - if (strcmp(reinterpret_cast<const char*>(name), "openmsx-control") == 0) { + if (strcmp(reinterpret_cast<const char*>(localname), + "openmsx-control") == 0) { parseState->state = TAG_OPENMSX; } else { ++(parseState->unknownLevel); } break; case TAG_OPENMSX: - if (strcmp(reinterpret_cast<const char*>(name), "command") == 0) { + if (strcmp(reinterpret_cast<const char*>(localname), + "command") == 0) { parseState->state = TAG_COMMAND; } else { ++(parseState->unknownLevel); @@ -171,7 +178,11 @@ parseState->content.clear(); } -void CliConnection::cb_end_element(void* user_data, const xmlChar* /*name*/) +void CliConnection::cb_end_element( + void* user_data, + const xmlChar* /*localname*/, const xmlChar* /*prefix*/, + const xmlChar* /*uri*/ + ) { ParseState* parseState = static_cast<ParseState*>(user_data); if (parseState->unknownLevel) { @@ -271,7 +282,7 @@ shutdownEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (shutdownEvent == NULL) { - throw FatalError("Error creating shutdown event: " + + throw FatalError("Error creating shutdown event: " + StringOp::toString(GetLastError())); } @@ -291,7 +302,7 @@ ZeroMemory(overlapped, sizeof(*overlapped)); overlapped->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); if (overlapped->hEvent == NULL) { - throw FatalError("Error creating overlapped event: " + + throw FatalError("Error creating overlapped event: " + StringOp::toString(GetLastError())); } } @@ -329,7 +340,7 @@ break; // Shutdown } else { - throw FatalError("WaitForMultipleObjects returned unexpectedly: " + + throw FatalError("WaitForMultipleObjects returned unexpectedly: " + StringOp::toString(wait)); } } Modified: openmsx/trunk/src/events/CliConnection.hh =================================================================== --- openmsx/trunk/src/events/CliConnection.hh 2009-06-10 01:27:05 UTC (rev 10018) +++ openmsx/trunk/src/events/CliConnection.hh 2009-06-11 00:32:59 UTC (rev 10019) @@ -73,9 +73,13 @@ CliConnection* object; }; - static void cb_start_element(void* user_data, const xmlChar* name, + static void cb_start_element(void* user_data, const xmlChar* localname, + const xmlChar* prefix, const xmlChar* uri, + int nb_namespaces, const xmlChar** namespaces, + int nb_attributes, int nb_defaulted, const xmlChar** attrs); - static void cb_end_element(void* user_data, const xmlChar* name); + static void cb_end_element(void* user_data, const xmlChar* localname, + const xmlChar* prefix, const xmlChar* uri); static void cb_text(void* user_data, const xmlChar* chars, int len); xmlSAXHandler sax_handler; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2009-06-30 18:24:33
|
Revision: 10104 http://openmsx.svn.sourceforge.net/openmsx/?rev=10104&view=rev Author: m9710797 Date: 2009-06-30 18:24:11 +0000 (Tue, 30 Jun 2009) Log Message: ----------- removed InputEvent base class Was only used to implement operator< but that could as well be done in the Event class itself. Modified Paths: -------------- openmsx/trunk/src/events/Event.cc openmsx/trunk/src/events/InputEvents.cc openmsx/trunk/src/events/InputEvents.hh Modified: openmsx/trunk/src/events/Event.cc =================================================================== --- openmsx/trunk/src/events/Event.cc 2009-06-30 18:23:49 UTC (rev 10103) +++ openmsx/trunk/src/events/Event.cc 2009-06-30 18:24:11 UTC (rev 10104) @@ -29,9 +29,11 @@ return result.getString(); } -bool Event::operator< (const Event& other) const +bool Event::operator<(const Event& other) const { - return lessImpl(other); + return (getType() != other.getType()) + ? (getType() < other.getType()) + : lessImpl(other); } bool Event::operator==(const Event& other) const Modified: openmsx/trunk/src/events/InputEvents.cc =================================================================== --- openmsx/trunk/src/events/InputEvents.cc 2009-06-30 18:23:49 UTC (rev 10103) +++ openmsx/trunk/src/events/InputEvents.cc 2009-06-30 18:24:11 UTC (rev 10104) @@ -20,19 +20,11 @@ { } -bool InputEvent::lessImpl(const Event& other) const -{ - const InputEvent* otherEvent = checked_cast<const InputEvent*>(&other); - return (getType() != otherEvent->getType()) - ? (getType() < otherEvent->getType()) - : lessImpl(*otherEvent); -} - // class KeyEvent KeyEvent::KeyEvent(EventType type, Keys::KeyCode keyCode_, word unicode_) - : InputEvent(type), keyCode(keyCode_), unicode(unicode_) + : Event(type), keyCode(keyCode_), unicode(unicode_) { } @@ -55,7 +47,7 @@ } } -bool KeyEvent::lessImpl(const InputEvent& other) const +bool KeyEvent::lessImpl(const Event& other) const { // note: don't compare unicode const KeyEvent* otherKeyEvent = checked_cast<const KeyEvent*>(&other); @@ -92,7 +84,7 @@ // class MouseButtonEvent MouseButtonEvent::MouseButtonEvent(EventType type, unsigned button_) - : InputEvent(type), button(button_) + : Event(type), button(button_) { } @@ -107,7 +99,7 @@ result.addListElement("button" + StringOp::toString(getButton())); } -bool MouseButtonEvent::lessImpl(const InputEvent& other) const +bool MouseButtonEvent::lessImpl(const Event& other) const { const MouseButtonEvent* otherMouseEvent = checked_cast<const MouseButtonEvent*>(&other); @@ -146,7 +138,7 @@ // class MouseMotionEvent MouseMotionEvent::MouseMotionEvent(int xrel_, int yrel_) - : InputEvent(OPENMSX_MOUSE_MOTION_EVENT), xrel(xrel_), yrel(yrel_) + : Event(OPENMSX_MOUSE_MOTION_EVENT), xrel(xrel_), yrel(yrel_) { } @@ -168,7 +160,7 @@ result.addListElement(getY()); } -bool MouseMotionEvent::lessImpl(const InputEvent& other) const +bool MouseMotionEvent::lessImpl(const Event& other) const { const MouseMotionEvent* otherMouseEvent = checked_cast<const MouseMotionEvent*>(&other); @@ -181,7 +173,7 @@ // class JoystickEvent JoystickEvent::JoystickEvent(EventType type, unsigned joystick_) - : InputEvent(type), joystick(joystick_) + : Event(type), joystick(joystick_) { } @@ -195,7 +187,7 @@ result.addListElement("joy" + StringOp::toString(getJoystick() + 1)); } -bool JoystickEvent::lessImpl(const InputEvent& other) const +bool JoystickEvent::lessImpl(const Event& other) const { const JoystickEvent* otherJoystickEvent = checked_cast<const JoystickEvent*>(&other); @@ -299,7 +291,7 @@ // class FocusEvent FocusEvent::FocusEvent(bool gain_) - : InputEvent(OPENMSX_FOCUS_EVENT), gain(gain_) + : Event(OPENMSX_FOCUS_EVENT), gain(gain_) { } @@ -314,7 +306,7 @@ result.addListElement(getGain()); } -bool FocusEvent::lessImpl(const InputEvent& other) const +bool FocusEvent::lessImpl(const Event& other) const { const FocusEvent* otherFocusEvent = checked_cast<const FocusEvent*>(&other); @@ -325,7 +317,7 @@ // class ResizeEvent ResizeEvent::ResizeEvent(unsigned x_, unsigned y_) - : InputEvent(OPENMSX_RESIZE_EVENT), x(x_), y(y_) + : Event(OPENMSX_RESIZE_EVENT), x(x_), y(y_) { } @@ -346,7 +338,7 @@ result.addListElement(int(getY())); } -bool ResizeEvent::lessImpl(const InputEvent& other) const +bool ResizeEvent::lessImpl(const Event& other) const { const ResizeEvent* otherResizeEvent = checked_cast<const ResizeEvent*>(&other); @@ -358,7 +350,7 @@ // class QuitEvent -QuitEvent::QuitEvent() : InputEvent(OPENMSX_QUIT_EVENT) +QuitEvent::QuitEvent() : Event(OPENMSX_QUIT_EVENT) { } @@ -367,7 +359,7 @@ result.addListElement("quit"); } -bool QuitEvent::lessImpl(const InputEvent& /*other*/) const +bool QuitEvent::lessImpl(const Event& /*other*/) const { return false; } @@ -376,7 +368,7 @@ // class MSXCommandEvent MSXCommandEvent::MSXCommandEvent(const vector<string>& tokens_) - : InputEvent(OPENMSX_MSX_COMMAND_EVENT) + : Event(OPENMSX_MSX_COMMAND_EVENT) , owned(true) { for (vector<string>::const_iterator it = tokens_.begin(); @@ -386,7 +378,7 @@ } MSXCommandEvent::MSXCommandEvent(const vector<TclObject*>& tokens_) - : InputEvent(OPENMSX_MSX_COMMAND_EVENT) + : Event(OPENMSX_MSX_COMMAND_EVENT) , tokens(tokens_) , owned(false) { @@ -416,7 +408,7 @@ } } -bool MSXCommandEvent::lessImpl(const InputEvent& other) const +bool MSXCommandEvent::lessImpl(const Event& other) const { const MSXCommandEvent* otherCommandEvent = checked_cast<const MSXCommandEvent*>(&other); Modified: openmsx/trunk/src/events/InputEvents.hh =================================================================== --- openmsx/trunk/src/events/InputEvents.hh 2009-06-30 18:23:49 UTC (rev 10103) +++ openmsx/trunk/src/events/InputEvents.hh 2009-06-30 18:24:11 UTC (rev 10104) @@ -14,13 +14,11 @@ class InputEvent : public Event { protected: - virtual bool lessImpl(const Event& other) const; - virtual bool lessImpl(const InputEvent& other) const = 0; explicit InputEvent(EventType type); }; -class KeyEvent : public InputEvent +class KeyEvent : public Event { public: Keys::KeyCode getKeyCode() const; @@ -31,7 +29,7 @@ private: virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; const Keys::KeyCode keyCode; const word unicode; }; @@ -51,7 +49,7 @@ }; -class MouseButtonEvent : public InputEvent +class MouseButtonEvent : public Event { public: static const unsigned LEFT = 1; @@ -67,7 +65,7 @@ void toStringHelper(TclObject& result) const; private: - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; const unsigned button; }; @@ -87,7 +85,7 @@ virtual void toStringImpl(TclObject& result) const; }; -class MouseMotionEvent : public InputEvent +class MouseMotionEvent : public Event { public: MouseMotionEvent(int xrel, int yrel); @@ -96,13 +94,13 @@ private: virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; const int xrel; const int yrel; }; -class JoystickEvent : public InputEvent +class JoystickEvent : public Event { public: unsigned getJoystick() const; @@ -112,7 +110,7 @@ void toStringHelper(TclObject& result) const; private: - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; virtual bool lessImpl(const JoystickEvent& other) const = 0; const unsigned joystick; }; @@ -165,7 +163,7 @@ }; -class FocusEvent : public InputEvent +class FocusEvent : public Event { public: explicit FocusEvent(bool gain); @@ -174,12 +172,12 @@ private: virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; const bool gain; }; -class ResizeEvent : public InputEvent +class ResizeEvent : public Event { public: ResizeEvent(unsigned x, unsigned y); @@ -189,19 +187,19 @@ private: virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; const unsigned x; const unsigned y; }; -class QuitEvent : public InputEvent +class QuitEvent : public Event { public: QuitEvent(); private: virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; }; @@ -209,7 +207,7 @@ * state (e.g. plug, disk<x>, cassetteplayer, reset). It's passed via an * event because the recording needs to see these. */ -class MSXCommandEvent : public InputEvent +class MSXCommandEvent : public Event { public: explicit MSXCommandEvent(const std::vector<std::string>& tokens); @@ -218,7 +216,7 @@ const std::vector<TclObject*>& getTokens() const; private: virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const InputEvent& other) const; + virtual bool lessImpl(const Event& other) const; std::vector<TclObject*> tokens; const bool owned; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2009-06-30 18:25:10
|
Revision: 10106 http://openmsx.svn.sourceforge.net/openmsx/?rev=10106&view=rev Author: m9710797 Date: 2009-06-30 18:24:50 +0000 (Tue, 30 Jun 2009) Log Message: ----------- small cleanup Removed an unused method, made another method private. Modified Paths: -------------- openmsx/trunk/src/events/InputEventGenerator.cc openmsx/trunk/src/events/InputEventGenerator.hh Modified: openmsx/trunk/src/events/InputEventGenerator.cc =================================================================== --- openmsx/trunk/src/events/InputEventGenerator.cc 2009-06-30 18:24:33 UTC (rev 10105) +++ openmsx/trunk/src/events/InputEventGenerator.cc 2009-06-30 18:24:50 UTC (rev 10106) @@ -82,13 +82,6 @@ } } -void InputEventGenerator::notify() -{ - static SDL_Event event; - event.type = SDL_USEREVENT; - SDL_PushEvent(&event); -} - void InputEventGenerator::setKeyRepeat(bool enable) { keyRepeat = enable; @@ -236,8 +229,8 @@ break; #if PLATFORM_GP2X - // SDL sees GP2X keys/joystick as a joystick events, for openMSX its - // easier to handle this as keyboard events (regular keys + cursors). + // SDL sees GP2X keys/joystick as joystick events, for openMSX it is + // easier to handle these as keyboard events (regular keys + cursors). // Code below remaps the events. This will probably have to be rewritten // to allow more dynamic mappings. case SDL_JOYBUTTONUP: Modified: openmsx/trunk/src/events/InputEventGenerator.hh =================================================================== --- openmsx/trunk/src/events/InputEventGenerator.hh 2009-06-30 18:24:33 UTC (rev 10105) +++ openmsx/trunk/src/events/InputEventGenerator.hh 2009-06-30 18:24:50 UTC (rev 10106) @@ -26,12 +26,10 @@ EventDistributor& eventDistributor); virtual ~InputEventGenerator(); - /** Poll / wait for an event and handle it. - * These methods should be called from the main thread. + /** Wait for event(s) and handle it. + * This method should be called from the main thread. */ void wait(); - void notify(); - void poll(); /** * Enable or disable keyboard event repeats @@ -49,6 +47,7 @@ BooleanSetting& getGrabInput() const { return *grabInput; } private: + void poll(); void handle(const SDL_Event& event); void setGrabInput(bool grab); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2009-09-15 19:34:38
|
Revision: 10585 http://openmsx.svn.sourceforge.net/openmsx/?rev=10585&view=rev Author: m9710797 Date: 2009-09-15 19:34:29 +0000 (Tue, 15 Sep 2009) Log Message: ----------- extend after command with msx events, part 1 Make AfterCommand class listen to MSXEventDistributor, it doesn't do anything yet with those events. Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/AfterCommand.hh openmsx/trunk/src/events/EventDistributor.cc Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2009-09-15 17:53:01 UTC (rev 10584) +++ openmsx/trunk/src/events/AfterCommand.cc 2009-09-15 19:34:29 UTC (rev 10585) @@ -5,6 +5,7 @@ #include "CliComm.hh" #include "Schedulable.hh" #include "EventDistributor.hh" +#include "MSXEventDistributor.hh" #include "Reactor.hh" #include "MSXMotherBoard.hh" #include "Alarm.hh" @@ -114,6 +115,7 @@ : SimpleCommand(commandController, "after") , reactor(reactor_) , eventDistributor(eventDistributor_) + , msxEvents(NULL) { // TODO DETACHED <-> EMU types should be cleaned up // (moved to event iso listener?) @@ -145,10 +147,16 @@ OPENMSX_MACHINE_LOADED_EVENT, *this); eventDistributor.registerEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); + + machineSwitch(); } AfterCommand::~AfterCommand() { + if (msxEvents) { + msxEvents->unregisterEventListener(*this); + } + eventDistributor.unregisterEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); eventDistributor.unregisterEventListener( @@ -393,6 +401,7 @@ } else if (event->getType() == OPENMSX_QUIT_EVENT) { executeEvents<OPENMSX_QUIT_EVENT>(); } else if (event->getType() == OPENMSX_MACHINE_LOADED_EVENT) { + machineSwitch(); executeEvents<OPENMSX_MACHINE_LOADED_EVENT>(); } else if (event->getType() == OPENMSX_AFTER_REALTIME_EVENT) { executeRealTime(); @@ -408,7 +417,25 @@ return true; } +void AfterCommand::machineSwitch() +{ + if (msxEvents) { + msxEvents->unregisterEventListener(*this); + } + MSXMotherBoard* motherBoard = reactor.getMotherBoard(); + msxEvents = motherBoard ? &motherBoard->getMSXEventDistributor() : NULL; + if (msxEvents) { + msxEvents->registerEventListener(*this); + } +} +void AfterCommand::signalEvent(shared_ptr<const Event> event, + EmuTime::param time) +{ + // TODO +} + + // class AfterCmd unsigned AfterCmd::lastAfterId = 0; Modified: openmsx/trunk/src/events/AfterCommand.hh =================================================================== --- openmsx/trunk/src/events/AfterCommand.hh 2009-09-15 17:53:01 UTC (rev 10584) +++ openmsx/trunk/src/events/AfterCommand.hh 2009-09-15 19:34:29 UTC (rev 10585) @@ -5,6 +5,7 @@ #include "Command.hh" #include "EventListener.hh" +#include "MSXEventListener.hh" #include "Event.hh" #include <vector> @@ -12,11 +13,13 @@ class Reactor; class EventDistributor; +class MSXEventDistributor; class CommandController; class AfterCmd; class Event; -class AfterCommand : public SimpleCommand, private EventListener +class AfterCommand : public SimpleCommand, private EventListener, + private MSXEventListener { public: AfterCommand(Reactor& reactor, @@ -39,13 +42,20 @@ std::string afterCancel(const std::vector<std::string>& tokens); void executeRealTime(); + void machineSwitch(); + // EventListener virtual bool signalEvent(shared_ptr<const Event> event); + // MSXEventListener + virtual void signalEvent(shared_ptr<const Event> event, + EmuTime::param time); + typedef std::vector<shared_ptr<AfterCmd> > AfterCmds; AfterCmds afterCmds; Reactor& reactor; EventDistributor& eventDistributor; + MSXEventDistributor* msxEvents; friend class AfterCmd; }; Modified: openmsx/trunk/src/events/EventDistributor.cc =================================================================== --- openmsx/trunk/src/events/EventDistributor.cc 2009-09-15 17:53:01 UTC (rev 10584) +++ openmsx/trunk/src/events/EventDistributor.cc 2009-09-15 19:34:29 UTC (rev 10585) @@ -75,32 +75,41 @@ void EventDistributor::deliverEvents() { ScopedLock lock(sem); - EventQueue eventsCopy; - swap(eventsCopy, scheduledEvents); + // It's possible that executing an event triggers scheduling of another + // event. We also want to execute those secondary events. That's why + // we have this while loop here. + // For example the 'loadstate' command event, triggers a machine switch + // event and as reaction to the latter event, AfterCommand will + // unsubscribe from the ols MSXEventDistributor. This really should be + // done before we exit this method. + while (!scheduledEvents.empty()) { + EventQueue eventsCopy; + swap(eventsCopy, scheduledEvents); - for (EventQueue::const_iterator it = eventsCopy.begin(); - it != eventsCopy.end(); ++it) { - EventPtr event = *it; - PriorityMap priorityMapCopy = listeners[event->getType()]; - sem.up(); - Priority currentPriority = OTHER; - bool stopEventDelivery = false; - for (PriorityMap::const_iterator it = priorityMapCopy.begin(); - it != priorityMapCopy.end(); ++it) { - if (currentPriority != it->first) { - currentPriority = it->first; - if (stopEventDelivery) { - break; + for (EventQueue::const_iterator it = eventsCopy.begin(); + it != eventsCopy.end(); ++it) { + EventPtr event = *it; + PriorityMap priorityMapCopy = listeners[event->getType()]; + sem.up(); + Priority currentPriority = OTHER; + bool stopEventDelivery = false; + for (PriorityMap::const_iterator it = priorityMapCopy.begin(); + it != priorityMapCopy.end(); ++it) { + if (currentPriority != it->first) { + currentPriority = it->first; + if (stopEventDelivery) { + break; + } } + if (!(it->second->signalEvent(event))) { + // only named priorities can prohibit events + // for lower priorities + assert(it->first != OTHER); + stopEventDelivery = true; + } } - if (!(it->second->signalEvent(event))) { - // only named priorities can prohibit events - // for lower priorities - assert(it->first != OTHER); - stopEventDelivery = true; - } + sem.down(); } - sem.down(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2009-09-15 19:34:58
|
Revision: 10586 http://openmsx.svn.sourceforge.net/openmsx/?rev=10586&view=rev Author: m9710797 Date: 2009-09-15 19:34:50 +0000 (Tue, 15 Sep 2009) Log Message: ----------- extend after command with msx events, part 2 Extend Tcl after command to also accept MSX event names. For example after "keyb UP" bar after "mouse button1 down" foo React to the MSXEvents (functionality introduced in previous patch). Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/AfterCommand.hh Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2009-09-15 19:34:29 UTC (rev 10585) +++ openmsx/trunk/src/events/AfterCommand.cc 2009-09-15 19:34:50 UTC (rev 10586) @@ -6,6 +6,7 @@ #include "Schedulable.hh" #include "EventDistributor.hh" #include "MSXEventDistributor.hh" +#include "InputEventFactory.hh" #include "Reactor.hh" #include "MSXMotherBoard.hh" #include "Alarm.hh" @@ -29,18 +30,18 @@ { public: virtual ~AfterCmd(); - const std::string& getCommand() const; - const std::string& getId() const; - virtual const std::string& getType() const = 0; + const string& getCommand() const; + const string& getId() const; + virtual string getType() const = 0; void execute(); protected: AfterCmd(AfterCommand& afterCommand, - const std::string& command); + const string& command); shared_ptr<AfterCmd> removeSelf(); private: AfterCommand& afterCommand; - std::string command; - std::string id; + string command; + string id; static unsigned lastAfterId; }; @@ -52,11 +53,11 @@ protected: AfterTimedCmd(Scheduler& scheduler, AfterCommand& afterCommand, - const std::string& command, double time); + const string& command, double time); private: virtual void executeUntil(EmuTime::param time, int userData); virtual void schedulerDeleted(); - virtual const std::string& schedName() const; + virtual const string& schedName() const; double time; }; @@ -66,8 +67,8 @@ public: AfterTimeCmd(Scheduler& scheduler, AfterCommand& afterCommand, - const std::string& command, double time); - virtual const std::string& getType() const; + const string& command, double time); + virtual string getType() const; }; class AfterIdleCmd : public AfterTimedCmd @@ -75,8 +76,8 @@ public: AfterIdleCmd(Scheduler& scheduler, AfterCommand& afterCommand, - const std::string& command, double time); - virtual const std::string& getType() const; + const string& command, double time); + virtual string getType() const; }; template<EventType T> @@ -84,21 +85,33 @@ { public: AfterEventCmd(AfterCommand& afterCommand, - const std::string& type, - const std::string& command); - virtual const std::string& getType() const; + const string& type, + const string& command); + virtual string getType() const; private: - const std::string type; + const string type; }; +class AfterMSXEventCmd : public AfterCmd +{ +public: + AfterMSXEventCmd(AfterCommand& afterCommand, + AfterCommand::EventPtr event, + const string& command); + virtual string getType() const; + AfterCommand::EventPtr getEvent() const { return event; } +private: + AfterCommand::EventPtr event; +}; + class AfterRealTimeCmd : public AfterCmd, private Alarm { public: AfterRealTimeCmd(AfterCommand& afterCommand, EventDistributor& eventDistributor, - const std::string& command, double time); + const string& command, double time); virtual ~AfterRealTimeCmd(); - virtual const std::string& getType() const; + virtual string getType() const; bool hasExpired() const; private: @@ -212,8 +225,15 @@ return afterInfo(tokens); } else if (tokens[1] == "cancel") { return afterCancel(tokens); + } else { + // try to interpret token as an event name + try { + EventPtr event(InputEventFactory::createInputEvent(tokens[1])); + return afterMSXEvent(event, tokens); + } catch (MSXException&) { + throw SyntaxError(); + } } - throw SyntaxError(); } static double getTime(const string& str) @@ -264,6 +284,16 @@ return cmd->getId(); } +string AfterCommand::afterMSXEvent(EventPtr event, const vector<string>& tokens) +{ + if (tokens.size() != 3) { + throw SyntaxError(); + } + shared_ptr<AfterCmd> cmd(new AfterMSXEventCmd(*this, event, tokens[2])); + afterCmds.push_back(cmd); + return cmd->getId(); +} + string AfterCommand::afterIdle(const vector<string>& tokens) { if (tokens.size() != 4) { @@ -349,6 +379,16 @@ // TODO : make more complete } +template<typename PRED> void AfterCommand::executeMatches(PRED pred) +{ + // predicate should return false on matches + AfterCmds::iterator it = partition(afterCmds.begin(), afterCmds.end(), pred); + AfterCmds tmp(it, afterCmds.end()); + afterCmds.erase(it, afterCmds.end()); + for (AfterCmds::iterator it = tmp.begin(); it != tmp.end(); ++it) { + (*it)->execute(); + } +} template<EventType T> struct AfterEventPred { bool operator()(shared_ptr<AfterCmd> x) const { @@ -357,14 +397,7 @@ }; template<EventType T> void AfterCommand::executeEvents() { - AfterCmds::iterator it = partition(afterCmds.begin(), afterCmds.end(), - AfterEventPred<T>()); - AfterCmds tmp(it, afterCmds.end()); - afterCmds.erase(it, afterCmds.end()); - - for (AfterCmds::iterator it = tmp.begin(); it != tmp.end(); ++it) { - (*it)->execute(); - } + executeMatches(AfterEventPred<T>()); } struct AfterTimePred { @@ -380,14 +413,7 @@ }; void AfterCommand::executeRealTime() { - AfterCmds::iterator it = partition(afterCmds.begin(), afterCmds.end(), - AfterTimePred()); - AfterCmds tmp(it, afterCmds.end()); - afterCmds.erase(it, afterCmds.end()); - - for (AfterCmds::iterator it = tmp.begin(); it != tmp.end(); ++it) { - (*it)->execute(); - } + executeMatches(AfterTimePred()); } bool AfterCommand::signalEvent(shared_ptr<const Event> event) @@ -429,10 +455,22 @@ } } + +struct AfterMSXEventPred { + AfterMSXEventPred(AfterCommand::EventPtr event_) + : event(event_) {} + bool operator()(shared_ptr<AfterCmd> x) const { + if (AfterMSXEventCmd* cmd = dynamic_cast<AfterMSXEventCmd*>(x.get())) { + if (*cmd->getEvent() == *event) return false; + } + return true; + } + AfterCommand::EventPtr event; +}; void AfterCommand::signalEvent(shared_ptr<const Event> event, EmuTime::param time) { - // TODO + executeMatches(AfterMSXEventPred(event)); } @@ -540,10 +578,9 @@ { } -const string& AfterTimeCmd::getType() const +string AfterTimeCmd::getType() const { - static const string type("time"); - return type; + return "time"; } @@ -557,10 +594,9 @@ { } -const string& AfterIdleCmd::getType() const +string AfterIdleCmd::getType() const { - static const string type("idle"); - return type; + return "idle"; } @@ -575,17 +611,32 @@ } template<EventType T> -const string& AfterEventCmd<T>::getType() const +string AfterEventCmd<T>::getType() const { return type; } +// AfterMSXEventCmd + +AfterMSXEventCmd::AfterMSXEventCmd( + AfterCommand& afterCommand, AfterCommand::EventPtr event_, + const string& command) + : AfterCmd(afterCommand, command) + , event(event_) +{ +} + +string AfterMSXEventCmd::getType() const +{ + return event->toString(); +} + // class AfterRealTimeCmd AfterRealTimeCmd::AfterRealTimeCmd( AfterCommand& afterCommand, EventDistributor& eventDistributor_, - const std::string& command, double time) + const string& command, double time) : AfterCmd(afterCommand, command) , eventDistributor(eventDistributor_) , expired(false) @@ -598,10 +649,9 @@ prepareDelete(); } -const std::string& AfterRealTimeCmd::getType() const +string AfterRealTimeCmd::getType() const { - static const string type("realtime"); - return type; + return "realtime"; } bool AfterRealTimeCmd::alarm() Modified: openmsx/trunk/src/events/AfterCommand.hh =================================================================== --- openmsx/trunk/src/events/AfterCommand.hh 2009-09-15 19:34:29 UTC (rev 10585) +++ openmsx/trunk/src/events/AfterCommand.hh 2009-09-15 19:34:50 UTC (rev 10586) @@ -7,6 +7,7 @@ #include "EventListener.hh" #include "MSXEventListener.hh" #include "Event.hh" +#include "shared_ptr.hh" #include <vector> namespace openmsx { @@ -22,6 +23,8 @@ private MSXEventListener { public: + typedef shared_ptr<const Event> EventPtr; + AfterCommand(Reactor& reactor, EventDistributor& eventDistributor, CommandController& commandController); @@ -32,9 +35,11 @@ virtual void tabCompletion(std::vector<std::string>& tokens) const; private: + template<typename PRED> void executeMatches(PRED pred); template<EventType T> void executeEvents(); template<EventType T> std::string afterEvent( const std::vector<std::string>& tokens); + std::string afterMSXEvent(EventPtr event, const std::vector<std::string>& tokens); std::string afterTime(const std::vector<std::string>& tokens); std::string afterRealTime(const std::vector<std::string>& tokens); std::string afterIdle(const std::vector<std::string>& tokens); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2010-09-12 18:22:35
|
Revision: 11677 http://openmsx.svn.sourceforge.net/openmsx/?rev=11677&view=rev Author: m9710797 Date: 2010-09-12 18:22:29 +0000 (Sun, 12 Sep 2010) Log Message: ----------- Use host input events instead of msx input events in 'after <event>' command. Before this patch the after command used MSX input events for stuff like: after "mouse button1 down" ... Now it uses host input events. An important difference between host and MSX input events (relevant for the after command) is that MSX events are not delivered when the MSX machine is paused. Because of this mouse clicks in the reversebar didn't work in pause mode. I browsed through SVN history and looked at the existing Tcl scripts that use 'after <input event>', but I couldn't find any reason why the after command used MSX events instead of host events. It's a bit strange because using MSX events is actually a bit more complex than using host events. Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/AfterCommand.hh Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2010-09-12 07:50:57 UTC (rev 11676) +++ openmsx/trunk/src/events/AfterCommand.cc 2010-09-12 18:22:29 UTC (rev 11677) @@ -5,7 +5,7 @@ #include "CliComm.hh" #include "Schedulable.hh" #include "EventDistributor.hh" -#include "MSXEventDistributor.hh" +#include "EventDistributor.hh" #include "InputEventFactory.hh" #include "Reactor.hh" #include "MSXMotherBoard.hh" @@ -93,11 +93,11 @@ const string type; }; -class AfterMSXEventCmd : public AfterCmd +class AfterInputEventCmd : public AfterCmd { public: - AfterMSXEventCmd(AfterCommand& afterCommand, - AfterCommand::EventPtr event, + AfterInputEventCmd(AfterCommand& afterCommand, + AfterCommand::EventPtr event, const string& command); virtual string getType() const; AfterCommand::EventPtr getEvent() const { return event; } @@ -129,7 +129,6 @@ : SimpleCommand(commandController, "after") , reactor(reactor_) , eventDistributor(eventDistributor_) - , msxEvents(NULL) { // TODO DETACHED <-> EMU types should be cleaned up // (moved to event iso listener?) @@ -161,16 +160,10 @@ OPENMSX_MACHINE_LOADED_EVENT, *this); eventDistributor.registerEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); - - machineSwitch(); } AfterCommand::~AfterCommand() { - if (msxEvents) { - msxEvents->unregisterEventListener(*this); - } - eventDistributor.unregisterEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); eventDistributor.unregisterEventListener( @@ -233,7 +226,7 @@ // try to interpret token as an event name try { EventPtr event(InputEventFactory::createInputEvent(tokens[1])); - return afterMSXEvent(event, tokens); + return afterInputEvent(event, tokens); } catch (MSXException&) { throw SyntaxError(); } @@ -297,12 +290,12 @@ return cmd->getId(); } -string AfterCommand::afterMSXEvent(EventPtr event, const vector<string>& tokens) +string AfterCommand::afterInputEvent(EventPtr event, const vector<string>& tokens) { if (tokens.size() != 3) { throw SyntaxError(); } - shared_ptr<AfterCmd> cmd(new AfterMSXEventCmd(*this, event, tokens[2])); + shared_ptr<AfterCmd> cmd(new AfterInputEventCmd(*this, event, tokens[2])); afterCmds.push_back(cmd); return cmd->getId(); } @@ -441,6 +434,19 @@ executeMatches(AfterTimePred()); } +struct AfterInputEventPred { + AfterInputEventPred(AfterCommand::EventPtr event_) + : event(event_) {} + bool operator()(shared_ptr<AfterCmd> x) const { + if (AfterInputEventCmd* cmd = + dynamic_cast<AfterInputEventCmd*>(x.get())) { + if (*cmd->getEvent() == *event) return false; + } + return true; + } + AfterCommand::EventPtr event; +}; + int AfterCommand::signalEvent(shared_ptr<const Event> event) { if (event->getType() == OPENMSX_FINISH_FRAME_EVENT) { @@ -452,11 +458,11 @@ } else if (event->getType() == OPENMSX_QUIT_EVENT) { executeEvents<OPENMSX_QUIT_EVENT>(); } else if (event->getType() == OPENMSX_MACHINE_LOADED_EVENT) { - machineSwitch(); executeEvents<OPENMSX_MACHINE_LOADED_EVENT>(); } else if (event->getType() == OPENMSX_AFTER_REALTIME_EVENT) { executeRealTime(); } else { + executeMatches(AfterInputEventPred(event)); for (AfterCmds::const_iterator it = afterCmds.begin(); it != afterCmds.end(); ++it) { if (AfterIdleCmd* idleCmd = @@ -468,37 +474,7 @@ return 0; } -void AfterCommand::machineSwitch() -{ - if (msxEvents) { - msxEvents->unregisterEventListener(*this); - } - MSXMotherBoard* motherBoard = reactor.getMotherBoard(); - msxEvents = motherBoard ? &motherBoard->getMSXEventDistributor() : NULL; - if (msxEvents) { - msxEvents->registerEventListener(*this); - } -} - -struct AfterMSXEventPred { - AfterMSXEventPred(AfterCommand::EventPtr event_) - : event(event_) {} - bool operator()(shared_ptr<AfterCmd> x) const { - if (AfterMSXEventCmd* cmd = dynamic_cast<AfterMSXEventCmd*>(x.get())) { - if (*cmd->getEvent() == *event) return false; - } - return true; - } - AfterCommand::EventPtr event; -}; -void AfterCommand::signalEvent(shared_ptr<const Event> event, - EmuTime::param /*time*/) -{ - executeMatches(AfterMSXEventPred(event)); -} - - // class AfterCmd unsigned AfterCmd::lastAfterId = 0; @@ -642,9 +618,9 @@ } -// AfterMSXEventCmd +// AfterInputEventCmd -AfterMSXEventCmd::AfterMSXEventCmd( +AfterInputEventCmd::AfterInputEventCmd( AfterCommand& afterCommand, AfterCommand::EventPtr event_, const string& command) : AfterCmd(afterCommand, command) @@ -652,7 +628,7 @@ { } -string AfterMSXEventCmd::getType() const +string AfterInputEventCmd::getType() const { return event->toString(); } Modified: openmsx/trunk/src/events/AfterCommand.hh =================================================================== --- openmsx/trunk/src/events/AfterCommand.hh 2010-09-12 07:50:57 UTC (rev 11676) +++ openmsx/trunk/src/events/AfterCommand.hh 2010-09-12 18:22:29 UTC (rev 11677) @@ -5,7 +5,6 @@ #include "Command.hh" #include "EventListener.hh" -#include "MSXEventListener.hh" #include "Event.hh" #include "shared_ptr.hh" #include <vector> @@ -14,13 +13,12 @@ class Reactor; class EventDistributor; -class MSXEventDistributor; +class EventDistributor; class CommandController; class AfterCmd; class Event; -class AfterCommand : public SimpleCommand, private EventListener, - private MSXEventListener +class AfterCommand : public SimpleCommand, private EventListener { public: typedef shared_ptr<const Event> EventPtr; @@ -39,7 +37,8 @@ template<EventType T> void executeEvents(); template<EventType T> std::string afterEvent( const std::vector<std::string>& tokens); - std::string afterMSXEvent(EventPtr event, const std::vector<std::string>& tokens); + std::string afterInputEvent(EventPtr event, + const std::vector<std::string>& tokens); std::string afterTime(const std::vector<std::string>& tokens); std::string afterRealTime(const std::vector<std::string>& tokens); std::string afterTclTime(int ms, const std::vector<std::string>& tokens); @@ -48,20 +47,13 @@ std::string afterCancel(const std::vector<std::string>& tokens); void executeRealTime(); - void machineSwitch(); - // EventListener virtual int signalEvent(shared_ptr<const Event> event); - // MSXEventListener - virtual void signalEvent(shared_ptr<const Event> event, - EmuTime::param time); - typedef std::vector<shared_ptr<AfterCmd> > AfterCmds; AfterCmds afterCmds; Reactor& reactor; EventDistributor& eventDistributor; - MSXEventDistributor* msxEvents; friend class AfterCmd; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <man...@us...> - 2010-12-11 15:21:09
|
Revision: 11808 http://openmsx.svn.sourceforge.net/openmsx/?rev=11808&view=rev Author: manuelbi Date: 2010-12-11 15:21:02 +0000 (Sat, 11 Dec 2010) Log Message: ----------- Avoid name clashes with ERROR, use LOGLEVEL_ERROR instead. Modified Paths: -------------- openmsx/trunk/src/events/CliComm.cc openmsx/trunk/src/events/CliComm.hh Modified: openmsx/trunk/src/events/CliComm.cc =================================================================== --- openmsx/trunk/src/events/CliComm.cc 2010-12-11 14:58:27 UTC (rev 11807) +++ openmsx/trunk/src/events/CliComm.cc 2010-12-11 15:21:02 UTC (rev 11808) @@ -34,7 +34,7 @@ void CliComm::printError(const std::string& message) { - log(ERROR, message); + log(LOGLEVEL_ERROR, message); } void CliComm::printProgress(const std::string& message) Modified: openmsx/trunk/src/events/CliComm.hh =================================================================== --- openmsx/trunk/src/events/CliComm.hh 2010-12-11 14:58:27 UTC (rev 11807) +++ openmsx/trunk/src/events/CliComm.hh 2010-12-11 15:21:02 UTC (rev 11808) @@ -13,7 +13,7 @@ enum LogLevel { INFO, WARNING, - ERROR, + LOGLEVEL_ERROR, // ERROR may give preprocessor name clashes PROGRESS, NUM_LEVELS // must be last }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2011-01-16 09:04:27
|
Revision: 11905 http://openmsx.svn.sourceforge.net/openmsx/?rev=11905&view=rev Author: m9710797 Date: 2011-01-16 09:04:21 +0000 (Sun, 16 Jan 2011) Log Message: ----------- Reverted part of commit 11895 Using std::map::operator[] or map::insert() in insert elements in a map is NOT equivalent: myMap[myKey] = myValue; This syntax requires that the key and value types can be default constructed (that's what revision 11895 changed). It will _overwrite_ the value for an existing key in the map. myMap.insert(make_pair(myKey, myValue); This will NOT overwrite an already exiting key. Revision Links: -------------- http://openmsx.svn.sourceforge.net/openmsx/?rev=11895&view=rev Modified Paths: -------------- openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/HotKey.hh Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2011-01-15 22:19:07 UTC (rev 11904) +++ openmsx/trunk/src/events/HotKey.cc 2011-01-16 09:04:21 UTC (rev 11905) @@ -225,7 +225,7 @@ unboundKeys.erase(event); boundKeys.insert(event); defaultMap.erase(event); - cmdMap.insert(std::make_pair(event, info)); + cmdMap[event] = info; saveBindings(commandController.getSettingsConfig().getXMLElement()); } @@ -248,9 +248,9 @@ if ((unboundKeys.find(event) == unboundKeys.end()) && (boundKeys.find(event) == boundKeys.end())) { // not explicity bound or unbound - cmdMap.insert(std::make_pair(event, info)); + cmdMap[event] = info; } - defaultMap.insert(std::make_pair(event, info)); + defaultMap[event] = info; } void HotKey::unbindDefault(EventPtr event) Modified: openmsx/trunk/src/events/HotKey.hh =================================================================== --- openmsx/trunk/src/events/HotKey.hh 2011-01-15 22:19:07 UTC (rev 11904) +++ openmsx/trunk/src/events/HotKey.hh 2011-01-16 09:04:21 UTC (rev 11905) @@ -39,10 +39,11 @@ private: struct HotKeyInfo { + HotKeyInfo() {} // for map::operator[] HotKeyInfo(const std::string& command_, bool repeat_ = false) : command(command_), repeat(repeat_) {} - const std::string command; - const bool repeat; + std::string command; + bool repeat; }; typedef std::map<EventPtr, HotKeyInfo, deref_less<EventPtr> > BindMap; typedef std::set<EventPtr, deref_less<EventPtr> > KeySet; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2011-08-06 07:40:07
|
Revision: 12222 http://openmsx.svn.sourceforge.net/openmsx/?rev=12222&view=rev Author: m9710797 Date: 2011-08-06 07:40:00 +0000 (Sat, 06 Aug 2011) Log Message: ----------- Fixed crash when clicking in reversebar This regression was recently introduced in revision 12219. The scenario that caused the crash went like this: - User clicks on the reversebar - A mouse-button-down event gets distributed to all the currently subscribed listeners (a copy of this list of listeners is made) - One of the listeners for this event is the OSDGUI layer. Via some Tcl scripts, a click in the reversebar will replace the current MSXMotherBoard with a new one at a different point in the timeline. - Another listener for the mouse event is the per MSXMotherBoard EventDelay class, but that one has just been deleted! To fix this problem, right before actually delivering an event to a listener, I now check if this listener is still actually subscribed. Note that it's (still) required to make a copy of the list of listeners because iterating over a changing STL collection is also undefined behavior (the collection changes when a listener (un)subscribes). Revision Links: -------------- http://openmsx.svn.sourceforge.net/openmsx/?rev=12219&view=rev Modified Paths: -------------- openmsx/trunk/src/events/EventDistributor.cc openmsx/trunk/src/events/EventDistributor.hh Modified: openmsx/trunk/src/events/EventDistributor.cc =================================================================== --- openmsx/trunk/src/events/EventDistributor.cc 2011-08-04 20:14:39 UTC (rev 12221) +++ openmsx/trunk/src/events/EventDistributor.cc 2011-08-06 07:40:00 UTC (rev 12222) @@ -73,6 +73,21 @@ } } +bool EventDistributor::isRegistered(EventType type, EventListener* listener) const +{ + TypeMap::const_iterator it = listeners.find(type); + if (it == listeners.end()) return false; + + const PriorityMap& priorityMap = it->second; + for (PriorityMap::const_iterator it2 = priorityMap.begin(); + it2 != priorityMap.end(); ++it2) { + if (it2->second == listener) { + return true; + } + } + return false; +} + void EventDistributor::deliverEvents() { assert(Thread::isMainThread()); @@ -92,11 +107,16 @@ for (EventQueue::const_iterator it = eventsCopy.begin(); it != eventsCopy.end(); ++it) { EventPtr event = *it; - PriorityMap priorityMapCopy = listeners[event->getType()]; + EventType type = event->getType(); + PriorityMap priorityMapCopy = listeners[type]; sem.up(); unsigned allowPriorities = unsigned(-1); // all priorities for (PriorityMap::const_iterator it = priorityMapCopy.begin(); it != priorityMapCopy.end(); ++it) { + // It's possible delivery to one of the previous + // Listeners unregistered the current Listener. + if (!isRegistered(type, it->second)) continue; + unsigned currentPriority = it->first; if (!(currentPriority & allowPriorities)) continue; Modified: openmsx/trunk/src/events/EventDistributor.hh =================================================================== --- openmsx/trunk/src/events/EventDistributor.hh 2011-08-04 20:14:39 UTC (rev 12221) +++ openmsx/trunk/src/events/EventDistributor.hh 2011-08-06 07:40:00 UTC (rev 12222) @@ -69,6 +69,8 @@ bool sleep(unsigned us); private: + bool isRegistered(EventType type, EventListener* listener) const; + Reactor& reactor; typedef std::multimap<Priority, EventListener*, std::greater<Priority> > This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <aw...@us...> - 2012-11-23 20:59:18
|
Revision: 12986 http://openmsx.svn.sourceforge.net/openmsx/?rev=12986&view=rev Author: awulms Date: 2012-11-23 20:59:11 +0000 (Fri, 23 Nov 2012) Log Message: ----------- Add virtual OSDcontrol event in order to aggregate joystick and cursor events into a more usable and convenient format for TCL OSD scripts Modified Paths: -------------- openmsx/trunk/src/events/Event.hh openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/HotKey.hh openmsx/trunk/src/events/InputEventFactory.cc openmsx/trunk/src/events/InputEventGenerator.cc openmsx/trunk/src/events/InputEventGenerator.hh openmsx/trunk/src/events/InputEvents.cc openmsx/trunk/src/events/InputEvents.hh Modified: openmsx/trunk/src/events/Event.hh =================================================================== --- openmsx/trunk/src/events/Event.hh 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/Event.hh 2012-11-23 20:59:11 UTC (rev 12986) @@ -23,6 +23,8 @@ OPENMSX_FOCUS_EVENT, OPENMSX_RESIZE_EVENT, OPENMSX_QUIT_EVENT, + OPENMSX_OSD_CONTROL_RELEASE_EVENT, + OPENMSX_OSD_CONTROL_PRESS_EVENT, OPENMSX_BOOT_EVENT, // sent when the MSX resets or power ups /** Sent when VDP (V99x8 or V9990) reaches the end of a frame */ Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/HotKey.cc 2012-11-23 20:59:11 UTC (rev 12986) @@ -89,10 +89,18 @@ OPENMSX_JOY_AXIS_MOTION_EVENT, *this, EventDistributor::HOTKEY); eventDistributor.registerEventListener( OPENMSX_FOCUS_EVENT, *this, EventDistributor::HOTKEY); + eventDistributor.registerEventListener( + OPENMSX_OSD_CONTROL_RELEASE_EVENT, *this, EventDistributor::HOTKEY); + eventDistributor.registerEventListener( + OPENMSX_OSD_CONTROL_PRESS_EVENT, *this, EventDistributor::HOTKEY); + + osdControlActive = false; } HotKey::~HotKey() { + eventDistributor.unregisterEventListener(OPENMSX_OSD_CONTROL_PRESS_EVENT, *this); + eventDistributor.unregisterEventListener(OPENMSX_OSD_CONTROL_RELEASE_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_FOCUS_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_JOY_BUTTON_UP_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_JOY_BUTTON_DOWN_EVENT, *this); @@ -162,6 +170,7 @@ if (!dynamic_cast<const KeyEvent*> (event.get()) && !dynamic_cast<const MouseButtonEvent*> (event.get()) && !dynamic_cast<const JoystickEvent*> (event.get()) && + !dynamic_cast<const OsdControlEvent*> (event.get()) && !dynamic_cast<const FocusEvent*> (event.get())) { throw CommandException("Unsupported event type"); } @@ -251,6 +260,10 @@ if ((unboundKeys.find(event) == unboundKeys.end()) && (boundKeys.find(event) == boundKeys.end())) { // not explicity bound or unbound + if (dynamic_cast<const OsdControlEvent*> (event.get())) { + // Binding an OSD Control event, implying that at least one is active + osdControlActive = true; + } cmdMap[event] = info; } defaultMap[event] = info; @@ -262,6 +275,18 @@ (boundKeys.find(event) == boundKeys.end())) { // not explicity bound or unbound cmdMap.erase(event); + // Validate if there is still at least one OsdControlEvent bound + bool osdControlStillActive = false; + for (auto it = cmdMap.begin(); + it != cmdMap.end(); ++it) { + EventPtr event = it->first; + if (dynamic_cast<const OsdControlEvent*> (event.get())) { + // There is still at least one OsdControlEvent in the cmdMap + osdControlStillActive = true; + break; + } + } + osdControlActive = osdControlStillActive; } defaultMap.erase(event); } @@ -277,7 +302,8 @@ } auto it = cmdMap.find(event); if (it == cmdMap.end()) { - return 0; + // Do not pass events to MSX when OsdControlEvents are bound + return osdControlActive ? EventDistributor::MSX : 0; } const HotKeyInfo& info = it->second; if (info.repeat) { Modified: openmsx/trunk/src/events/HotKey.hh =================================================================== --- openmsx/trunk/src/events/HotKey.hh 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/HotKey.hh 2012-11-23 20:59:11 UTC (rev 12986) @@ -73,6 +73,7 @@ GlobalCommandController& commandController; EventDistributor& eventDistributor; EventPtr lastEvent; + bool osdControlActive; }; } // namespace openmsx Modified: openmsx/trunk/src/events/InputEventFactory.cc =================================================================== --- openmsx/trunk/src/events/InputEventFactory.cc 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/InputEventFactory.cc 2012-11-23 20:59:11 UTC (rev 12986) @@ -5,6 +5,7 @@ #include "CommandException.hh" #include "StringOp.hh" #include "Interpreter.hh" +#include "openmsx.hh" using std::string; using std::vector; @@ -80,6 +81,45 @@ } } +static EventPtr parseOsdControlEvent( + const string& str, const vector<string>& components) +{ +#ifdef DEBUG + ad_printf("components.size(): %d\n", components.size()); + for (unsigned cnt=0; cnt != components.size(); cnt++) { + ad_printf("component[%d]: %s\n", cnt, components[cnt].c_str()); + } +#endif + if (components.size() != 3) { + throw CommandException("Invalid OSDcontrol event: " + str); + } + string buttonName = components[1]; + unsigned button; + if (buttonName == "LEFT") { + button = OsdControlEvent::LEFT_BUTTON; + } else if (buttonName == "RIGHT") { + button = OsdControlEvent::RIGHT_BUTTON; + } else if (buttonName == "UP") { + button = OsdControlEvent::UP_BUTTON; + } else if (buttonName == "DOWN") { + button = OsdControlEvent::DOWN_BUTTON; + } else if (buttonName == "A") { + button = OsdControlEvent::A_BUTTON; + } else if (buttonName == "B") { + button = OsdControlEvent::B_BUTTON; + } else { + throw CommandException("Invalid OSDcontrol event: " + str); + } + if (components[2] == "RELEASE") { + return make_shared<OsdControlReleaseEvent>(button); + } else if (components[2] == "PRESS") { + return make_shared<OsdControlPressEvent>(button); + } + else { + throw CommandException("Invalid OSDcontrol event: " + str); + } +} + static EventPtr parseJoystickEvent( const string& str, const vector<string>& components) { @@ -171,6 +211,8 @@ } else if (components[0] == "command") { return EventPtr(); //return parseCommandEvent(str, components); + } else if (components[0] == "OSDcontrol") { + return parseOsdControlEvent(str, components); } else { // fall back return parseKeyEvent(components[0], 0); Modified: openmsx/trunk/src/events/InputEventGenerator.cc =================================================================== --- openmsx/trunk/src/events/InputEventGenerator.cc 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/InputEventGenerator.cc 2012-11-23 20:59:11 UTC (rev 12986) @@ -50,6 +50,8 @@ eventDistributor.registerEventListener(OPENMSX_POLL_EVENT, *this); reinit(); + + osdControlButtonsState = ~0; // 0 is pressed, 1 is released } InputEventGenerator::~InputEventGenerator() @@ -201,25 +203,157 @@ } #endif + +#ifdef ANDROID +//TODO: make JOYVALUE_THRESHOLD dynamic, depending on virtual key size +static const int JOYVALUE_THRESHOLD = 32768 / 4; +#else +static const int JOYVALUE_THRESHOLD = 32768 / 10; +#endif + +void InputEventGenerator::setNewOsdControlButtonState( + unsigned newState) +{ + EventDistributor::EventPtr event; + unsigned deltaState = osdControlButtonsState ^ newState; + for (unsigned i = OsdControlEvent::LEFT_BUTTON; + i <= OsdControlEvent::B_BUTTON; ++i) { + if (deltaState & (1 << i)) { + if (newState & (1 << i)) { + eventDistributor.distributeEvent(make_shared<OsdControlReleaseEvent>(i)); + } else { + eventDistributor.distributeEvent(make_shared<OsdControlPressEvent>(i)); + } + } + } + osdControlButtonsState = newState; +} + +void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion( + unsigned axis, + short value) +{ + short normalized_value = (value < -JOYVALUE_THRESHOLD ? -1 : (value > JOYVALUE_THRESHOLD ? 1 : 0)); + unsigned neg_button, pos_button; + + switch (axis) { + case 0: + neg_button = 1<<OsdControlEvent::LEFT_BUTTON; + pos_button = 1<<OsdControlEvent::RIGHT_BUTTON; + break; // axis 0 + case 1: + neg_button = 1<<OsdControlEvent::UP_BUTTON; + pos_button = 1<<OsdControlEvent::DOWN_BUTTON; + break; + default: + // Ignore all other axis (3D joysticks and flight joysticks may have more then 2 axis) + return; + } + switch(normalized_value) { + case 0: + // release both buttons + setNewOsdControlButtonState( + osdControlButtonsState | neg_button | pos_button); + break; + case 1: + // release negative button, press positive button + setNewOsdControlButtonState( + (osdControlButtonsState | neg_button) & ~pos_button); + break; + case -1: + // press negative button, release positive button + setNewOsdControlButtonState( + (osdControlButtonsState | pos_button) & ~neg_button); + break; + } +} + +void InputEventGenerator::osdControlChangeButton( + bool up, unsigned changedButtonMask) +{ + auto newButtonState = up + ? osdControlButtonsState | changedButtonMask + : osdControlButtonsState & ~changedButtonMask; + setNewOsdControlButtonState(newButtonState); +} + +void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent( + unsigned button, bool up) +{ + osdControlChangeButton(up, + (button & 1) ? 1<<OsdControlEvent::B_BUTTON : 1<<OsdControlEvent::A_BUTTON); +} + +void InputEventGenerator::triggerOsdControlEventsFromKeyEvent( + Keys::KeyCode keyCode, + bool up) +{ + keyCode = static_cast<Keys::KeyCode>(keyCode & Keys::K_MASK); + if (keyCode == Keys::K_LEFT) { + osdControlChangeButton(up, 1<<OsdControlEvent::LEFT_BUTTON); + } else if (keyCode == Keys::K_RIGHT) { + osdControlChangeButton(up, 1<<OsdControlEvent::RIGHT_BUTTON); + } else if (keyCode == Keys::K_UP) { + osdControlChangeButton(up, 1<<OsdControlEvent::UP_BUTTON); + } else if (keyCode == Keys::K_DOWN) { + osdControlChangeButton(up, 1<<OsdControlEvent::DOWN_BUTTON); + } else if (keyCode == Keys::K_SPACE || keyCode == Keys::K_RETURN) { + osdControlChangeButton(up, 1<<OsdControlEvent::A_BUTTON); + } else if (keyCode == Keys::K_ESCAPE) { + osdControlChangeButton(up, 1<<OsdControlEvent::B_BUTTON); + } +} + void InputEventGenerator::handle(const SDL_Event& evt) { EventDistributor::EventPtr event; + Keys::KeyCode keyCode; switch (evt.type) { case SDL_KEYUP: - event = make_shared<KeyUpEvent>( - Keys::getCode(evt.key.keysym.sym, - evt.key.keysym.mod, - evt.key.keysym.scancode, - true), - evt.key.keysym.unicode); +#ifdef ANDROID + // Virtual joystick of SDL Android port does not have joystick buttons. + // It has however up to 6 virtual buttons that can be mapped to SDL keyboard + // events. Two of these virtual buttons will be mapped to keys SDLK_WORLD_93 and 94 + // and are interpeted here as joystick buttons (respectively button 0 and 1). + if (evt.key.keysym.sym == SDLK_WORLD_93) { + event = make_shared<JoystickButtonUpEvent>(0, 0); + triggerOsdControlEventsFromJoystickButtonEvent(0, true); + } else if (evt.key.keysym.sym == SDLK_WORLD_94) { + event = make_shared<JoystickButtonUpEvent>(0, 1); + triggerOsdControlEventsFromJoystickButtonEvent(1, true); + } else { +#endif + keyCode = Keys::getCode( + evt.key.keysym.sym, + evt.key.keysym.mod, + evt.key.keysym.scancode, + true); + event = make_shared<KeyUpEvent>(keyCode, evt.key.keysym.unicode); + triggerOsdControlEventsFromKeyEvent(keyCode, true); +#ifdef ANDROID + } +#endif break; case SDL_KEYDOWN: - event = make_shared<KeyDownEvent>( - Keys::getCode(evt.key.keysym.sym, - evt.key.keysym.mod, - evt.key.keysym.scancode, - false), - evt.key.keysym.unicode); +#ifdef ANDROID + if (evt.key.keysym.sym == SDLK_WORLD_93) { + event = make_shared<JoystickButtonDownEvent>(0, 0); + triggerOsdControlEventsFromJoystickButtonEvent(0, false); + } else if (evt.key.keysym.sym == SDLK_WORLD_94) { + event = make_shared<JoystickButtonDownEvent>(0, 1); + triggerOsdControlEventsFromJoystickButtonEvent(1, false); + } else { +#endif + keyCode = Keys::getCode( + evt.key.keysym.sym, + evt.key.keysym.mod, + evt.key.keysym.scancode, + false); + event = make_shared<KeyDownEvent>(keyCode, evt.key.keysym.unicode); + triggerOsdControlEventsFromKeyEvent(keyCode, false); +#ifdef ANDROID + } +#endif break; case SDL_MOUSEBUTTONUP: @@ -266,10 +400,14 @@ } #else case SDL_JOYBUTTONUP: + triggerOsdControlEventsFromJoystickButtonEvent( + evt.jbutton.button, true); event = make_shared<JoystickButtonUpEvent>( evt.jbutton.which, evt.jbutton.button); break; case SDL_JOYBUTTONDOWN: + triggerOsdControlEventsFromJoystickButtonEvent( + evt.jbutton.button, false); event = make_shared<JoystickButtonDownEvent>( evt.jbutton.which, evt.jbutton.button); break; @@ -277,6 +415,8 @@ case SDL_JOYAXISMOTION: event = make_shared<JoystickAxisMotionEvent>( evt.jaxis.which, evt.jaxis.axis, evt.jaxis.value); + triggerOsdControlEventsFromJoystickAxisMotion( + evt.jaxis.axis, evt.jaxis.value); break; case SDL_ACTIVEEVENT: Modified: openmsx/trunk/src/events/InputEventGenerator.hh =================================================================== --- openmsx/trunk/src/events/InputEventGenerator.hh 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/InputEventGenerator.hh 2012-11-23 20:59:11 UTC (rev 12986) @@ -7,6 +7,7 @@ #include "EventListener.hh" #include "noncopyable.hh" #include "build-info.hh" +#include "Keys.hh" #include <SDL.h> #include <memory> @@ -68,10 +69,20 @@ ESCAPE_GRAB_WAIT_GAIN } escapeGrabState; + // OsdControl + void setNewOsdControlButtonState(unsigned newState); + void triggerOsdControlEventsFromJoystickAxisMotion(unsigned axis, short value); + void osdControlChangeButton(bool up, unsigned changedButtonMask); + void triggerOsdControlEventsFromJoystickButtonEvent(unsigned button, bool up); + void triggerOsdControlEventsFromKeyEvent(Keys::KeyCode keyCode, bool up); + + #if PLATFORM_GP2X int stat8; // last joystick status (8 input switches) #endif bool keyRepeat; + + unsigned osdControlButtonsState; // 0 is pressed, 1 is released }; } // namespace openmsx Modified: openmsx/trunk/src/events/InputEvents.cc =================================================================== --- openmsx/trunk/src/events/InputEvents.cc 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/InputEvents.cc 2012-11-23 20:59:11 UTC (rev 12986) @@ -365,4 +365,61 @@ return false; } +// class OsdControlEvent + +OsdControlEvent::OsdControlEvent(EventType type, unsigned button_) + : TimedEvent(type), button(button_) +{ +} + +unsigned OsdControlEvent::getButton() const +{ + return button; +} + +void OsdControlEvent::toStringHelper(TclObject& result) const +{ + result.addListElement("OSDcontrol"); + static const char* const names[] = { + "LEFT", "RIGHT", "UP", "DOWN", "A", "B" + }; + result.addListElement(names[getButton()]); +} + +bool OsdControlEvent::lessImpl(const Event& other) const +{ + const OsdControlEvent* otherOsdControlEvent = + checked_cast<const OsdControlEvent*>(&other); + return getButton() < otherOsdControlEvent->getButton(); +} + + +// class OsdControlReleaseEvent + +OsdControlReleaseEvent::OsdControlReleaseEvent(unsigned button) + : OsdControlEvent(OPENMSX_OSD_CONTROL_RELEASE_EVENT, button) +{ +} + +void OsdControlReleaseEvent::toStringImpl(TclObject& result) const +{ + toStringHelper(result); + result.addListElement("RELEASE"); +} + + +// class OsdControlPressEvent + +OsdControlPressEvent::OsdControlPressEvent(unsigned button) + : OsdControlEvent(OPENMSX_OSD_CONTROL_PRESS_EVENT, button) +{ +} + +void OsdControlPressEvent::toStringImpl(TclObject& result) const +{ + toStringHelper(result); + result.addListElement("PRESS"); +} + + } // namespace openmsx Modified: openmsx/trunk/src/events/InputEvents.hh =================================================================== --- openmsx/trunk/src/events/InputEvents.hh 2012-11-20 21:22:52 UTC (rev 12985) +++ openmsx/trunk/src/events/InputEvents.hh 2012-11-23 20:59:11 UTC (rev 12986) @@ -207,6 +207,47 @@ virtual bool lessImpl(const Event& other) const; }; +class OsdControlEvent : public TimedEvent +{ +public: + enum { LEFT_BUTTON, RIGHT_BUTTON, UP_BUTTON, DOWN_BUTTON, + A_BUTTON, B_BUTTON }; + + /* + static const unsigned LEFT_BUTTON = 1; + static const unsigned RIGHT_BUTTON = 2; + static const unsigned UP_BUTTON = 3; + static const unsigned DOWN_BUTTON = 4; + static const unsigned A_BUTTON = 5; + static const unsigned B_BUTTON = 6; +*/ + unsigned getButton() const; + +protected: + OsdControlEvent(EventType type, unsigned button_); + void toStringHelper(TclObject& result) const; + +private: + virtual bool lessImpl(const Event& other) const; + const unsigned button; +}; + +class OsdControlReleaseEvent : public OsdControlEvent +{ +public: + explicit OsdControlReleaseEvent(unsigned button); +private: + virtual void toStringImpl(TclObject& result) const; +}; + +class OsdControlPressEvent : public OsdControlEvent +{ +public: + explicit OsdControlPressEvent(unsigned button); +private: + virtual void toStringImpl(TclObject& result) const; +}; + } // namespace openmsx #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2012-12-01 15:08:49
|
Revision: 12999 http://openmsx.svn.sourceforge.net/openmsx/?rev=12999&view=rev Author: m9710797 Date: 2012-12-01 15:08:43 +0000 (Sat, 01 Dec 2012) Log Message: ----------- [1/4] Implement input layer system: remove hack Revision 12986 implemented a hack: as soon as there is one OSDControl event bound to a Tcl command, all events (so also the unbound events) are blocked from reaching the emulated MSX. This patch series replaces that hack with a cleaner input layer system. This patch only removes the hack. Revision Links: -------------- http://openmsx.svn.sourceforge.net/openmsx/?rev=12986&view=rev Modified Paths: -------------- openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/HotKey.hh Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2012-12-01 15:08:26 UTC (rev 12998) +++ openmsx/trunk/src/events/HotKey.cc 2012-12-01 15:08:43 UTC (rev 12999) @@ -93,8 +93,6 @@ OPENMSX_OSD_CONTROL_RELEASE_EVENT, *this, EventDistributor::HOTKEY); eventDistributor.registerEventListener( OPENMSX_OSD_CONTROL_PRESS_EVENT, *this, EventDistributor::HOTKEY); - - osdControlActive = false; } HotKey::~HotKey() @@ -260,10 +258,6 @@ if ((unboundKeys.find(event) == unboundKeys.end()) && (boundKeys.find(event) == boundKeys.end())) { // not explicity bound or unbound - if (dynamic_cast<const OsdControlEvent*> (event.get())) { - // Binding an OSD Control event, implying that at least one is active - osdControlActive = true; - } cmdMap[event] = info; } defaultMap[event] = info; @@ -275,18 +269,6 @@ (boundKeys.find(event) == boundKeys.end())) { // not explicity bound or unbound cmdMap.erase(event); - // Validate if there is still at least one OsdControlEvent bound - bool osdControlStillActive = false; - for (auto it = cmdMap.begin(); - it != cmdMap.end(); ++it) { - EventPtr event = it->first; - if (dynamic_cast<const OsdControlEvent*> (event.get())) { - // There is still at least one OsdControlEvent in the cmdMap - osdControlStillActive = true; - break; - } - } - osdControlActive = osdControlStillActive; } defaultMap.erase(event); } @@ -302,8 +284,7 @@ } auto it = cmdMap.find(event); if (it == cmdMap.end()) { - // Do not pass events to MSX when OsdControlEvents are bound - return osdControlActive ? EventDistributor::MSX : 0; + return 0; } const HotKeyInfo& info = it->second; if (info.repeat) { Modified: openmsx/trunk/src/events/HotKey.hh =================================================================== --- openmsx/trunk/src/events/HotKey.hh 2012-12-01 15:08:26 UTC (rev 12998) +++ openmsx/trunk/src/events/HotKey.hh 2012-12-01 15:08:43 UTC (rev 12999) @@ -73,7 +73,6 @@ GlobalCommandController& commandController; EventDistributor& eventDistributor; EventPtr lastEvent; - bool osdControlActive; }; } // namespace openmsx This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2013-02-07 19:41:13
|
Revision: 13156 http://openmsx.svn.sourceforge.net/openmsx/?rev=13156&view=rev Author: m9710797 Date: 2013-02-07 19:41:03 +0000 (Thu, 07 Feb 2013) Log Message: ----------- Fixed 'bind -repeat' for OsdControlEvents This should fix key-repeat in the OSD menu. There are some comments in the code that explain what was going on and how it's fixed. Modified Paths: -------------- openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/InputEventFactory.cc openmsx/trunk/src/events/InputEventGenerator.cc openmsx/trunk/src/events/InputEventGenerator.hh openmsx/trunk/src/events/InputEvents.cc openmsx/trunk/src/events/InputEvents.hh Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2013-02-06 19:49:18 UTC (rev 13155) +++ openmsx/trunk/src/events/HotKey.cc 2013-02-07 19:41:03 UTC (rev 13156) @@ -363,8 +363,23 @@ if (event->getType() == OPENMSX_REPEAT_HOTKEY) { if (!lastEvent.get()) return true; event = lastEvent; - } else if (lastEvent.get() && (*lastEvent != *event)) { - stopRepeat(); + } else if (lastEvent.get() != event.get()) { + // If the newly received event is different from the repeating + // event, we stop the repeat process. + // Except when we're repeating a OsdControlEvent and the + // received event was actually the 'generating' event for the + // Osd event. E.g. a cursor-keyboard-down event will generate + // a corresponding osd event (the osd event is send before the + // original event). Without this hack, key-repeat will not work + // for osd key bindings. + bool stop = true; + if (auto osdEv = dynamic_cast<const OsdControlEvent*>( + lastEvent.get())) { + if (osdEv->getOriginalEvent() == event.get()) { + stop = false; + } + } + if (stop) stopRepeat(); } // First search in active layers (from back to front) Modified: openmsx/trunk/src/events/InputEventFactory.cc =================================================================== --- openmsx/trunk/src/events/InputEventFactory.cc 2013-02-06 19:49:18 UTC (rev 13155) +++ openmsx/trunk/src/events/InputEventFactory.cc 2013-02-07 19:41:03 UTC (rev 13156) @@ -111,9 +111,9 @@ throw CommandException("Invalid OSDcontrol event: " + str); } if (components[2] == "RELEASE") { - return make_shared<OsdControlReleaseEvent>(button); + return make_shared<OsdControlReleaseEvent>(button, nullptr); } else if (components[2] == "PRESS") { - return make_shared<OsdControlPressEvent>(button); + return make_shared<OsdControlPressEvent>(button, nullptr); } else { throw CommandException("Invalid OSDcontrol event: " + str); Modified: openmsx/trunk/src/events/InputEventGenerator.cc =================================================================== --- openmsx/trunk/src/events/InputEventGenerator.cc 2013-02-06 19:49:18 UTC (rev 13155) +++ openmsx/trunk/src/events/InputEventGenerator.cc 2013-02-07 19:41:03 UTC (rev 13156) @@ -85,27 +85,27 @@ SDL_Event event; while (SDL_PollEvent(&event) == 1) { #ifdef DEBUG - string evtType; + string t; switch (event.type) { - case SDL_ACTIVEEVENT: evtType = "SDL_ACTIVEEVENT"; break; - case SDL_KEYDOWN: evtType = "SDL_KEYDOWN"; break; - case SDL_KEYUP: evtType = "SDL_KEYUP"; break; - case SDL_MOUSEMOTION: evtType = "SDL_MOUSEMOTION"; break; - case SDL_MOUSEBUTTONDOWN: evtType = "SDL_MOUSEBUTTONDOWN"; break; - case SDL_MOUSEBUTTONUP: evtType = "SDL_MOUSEBUTTONUP"; break; - case SDL_JOYAXISMOTION: evtType = "SDL_JOYAXISMOTION"; break; - case SDL_JOYBALLMOTION: evtType = "SDL_JOYBALLMOTION"; break; - case SDL_JOYHATMOTION: evtType = "SDL_JOYHATMOTION"; break; - case SDL_JOYBUTTONDOWN: evtType = "SDL_JOYBUTTONDOWN"; break; - case SDL_JOYBUTTONUP: evtType = "SDL_JOYBUTTONUP"; break; - case SDL_QUIT: evtType = "SDL_QUIT"; break; - case SDL_SYSWMEVENT: evtType = "SDL_SYSWMEVENT"; break; - case SDL_VIDEORESIZE: evtType = "SDL_VIDEORESIZE"; break; - case SDL_VIDEOEXPOSE: evtType = "SDL_VIDEOEXPOSE"; break; - case SDL_USEREVENT: evtType = "SDL_USEREVENT"; break; - default: evtType = "UNKNOWN"; break; + case SDL_ACTIVEEVENT: t = "SDL_ACTIVEEVENT"; break; + case SDL_KEYDOWN: t = "SDL_KEYDOWN"; break; + case SDL_KEYUP: t = "SDL_KEYUP"; break; + case SDL_MOUSEMOTION: t = "SDL_MOUSEMOTION"; break; + case SDL_MOUSEBUTTONDOWN: t = "SDL_MOUSEBUTTONDOWN"; break; + case SDL_MOUSEBUTTONUP: t = "SDL_MOUSEBUTTONUP"; break; + case SDL_JOYAXISMOTION: t = "SDL_JOYAXISMOTION"; break; + case SDL_JOYBALLMOTION: t = "SDL_JOYBALLMOTION"; break; + case SDL_JOYHATMOTION: t = "SDL_JOYHATMOTION"; break; + case SDL_JOYBUTTONDOWN: t = "SDL_JOYBUTTONDOWN"; break; + case SDL_JOYBUTTONUP: t = "SDL_JOYBUTTONUP"; break; + case SDL_QUIT: t = "SDL_QUIT"; break; + case SDL_SYSWMEVENT: t = "SDL_SYSWMEVENT"; break; + case SDL_VIDEORESIZE: t = "SDL_VIDEORESIZE"; break; + case SDL_VIDEOEXPOSE: t = "SDL_VIDEOEXPOSE"; break; + case SDL_USEREVENT: t = "SDL_USEREVENT"; break; + default: t = "UNKNOWN"; break; } - PRT_DEBUG("SDL event received, type: " + evtType); + PRT_DEBUG("SDL event received, type: " + t); #endif handle(event); } @@ -148,9 +148,11 @@ static EventDistributor::EventPtr createKeyEvent(Keys::KeyCode key, bool up) { if (up) { - return make_shared<KeyUpEvent >(Keys::combine(key, Keys::KD_RELEASE), 0); + return make_shared<KeyUpEvent>( + Keys::combine(key, Keys::KD_RELEASE), 0); } else { - return make_shared<KeyDownEvent<(Keys::combine(key, Keys::KD_PRESS), 0); + return make_shared<KeyDownEvent<( + Keys::combine(key, Keys::KD_PRESS), 0); } } @@ -235,17 +237,21 @@ #endif void InputEventGenerator::setNewOsdControlButtonState( - unsigned newState) + unsigned newState, const EventPtr& origEvent) { - EventDistributor::EventPtr event; + EventPtr event; unsigned deltaState = osdControlButtonsState ^ newState; for (unsigned i = OsdControlEvent::LEFT_BUTTON; i <= OsdControlEvent::B_BUTTON; ++i) { if (deltaState & (1 << i)) { if (newState & (1 << i)) { - eventDistributor.distributeEvent(make_shared<OsdControlReleaseEvent>(i)); + eventDistributor.distributeEvent( + make_shared<OsdControlReleaseEvent>( + i, origEvent)); } else { - eventDistributor.distributeEvent(make_shared<OsdControlPressEvent>(i)); + eventDistributor.distributeEvent( + make_shared<OsdControlPressEvent>( + i, origEvent)); } } } @@ -253,121 +259,137 @@ } void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion( - unsigned axis, - short value) + unsigned axis, short value, const EventPtr& origEvent) { - short normalized_value = (value < -JOYVALUE_THRESHOLD ? -1 : (value > JOYVALUE_THRESHOLD ? 1 : 0)); + short normalized_value = (value < -JOYVALUE_THRESHOLD + ? -1 + : (value > JOYVALUE_THRESHOLD ? 1 : 0)); unsigned neg_button, pos_button; switch (axis) { case 0: - neg_button = 1<<OsdControlEvent::LEFT_BUTTON; - pos_button = 1<<OsdControlEvent::RIGHT_BUTTON; + neg_button = 1 << OsdControlEvent::LEFT_BUTTON; + pos_button = 1 << OsdControlEvent::RIGHT_BUTTON; break; // axis 0 case 1: - neg_button = 1<<OsdControlEvent::UP_BUTTON; - pos_button = 1<<OsdControlEvent::DOWN_BUTTON; + neg_button = 1 << OsdControlEvent::UP_BUTTON; + pos_button = 1 << OsdControlEvent::DOWN_BUTTON; break; default: - // Ignore all other axis (3D joysticks and flight joysticks may have more then 2 axis) + // Ignore all other axis (3D joysticks and flight joysticks may + // have more than 2 axis) return; } - switch(normalized_value) { + switch (normalized_value) { case 0: // release both buttons setNewOsdControlButtonState( - osdControlButtonsState | neg_button | pos_button); + osdControlButtonsState | neg_button | pos_button, + origEvent); break; case 1: // release negative button, press positive button setNewOsdControlButtonState( - (osdControlButtonsState | neg_button) & ~pos_button); + (osdControlButtonsState | neg_button) & ~pos_button, + origEvent); break; case -1: // press negative button, release positive button setNewOsdControlButtonState( - (osdControlButtonsState | pos_button) & ~neg_button); + (osdControlButtonsState | pos_button) & ~neg_button, + origEvent); break; } } void InputEventGenerator::osdControlChangeButton( - bool up, unsigned changedButtonMask) + bool up, unsigned changedButtonMask, const EventPtr& origEvent) { auto newButtonState = up - ? osdControlButtonsState | changedButtonMask - : osdControlButtonsState & ~changedButtonMask; - setNewOsdControlButtonState(newButtonState); + ? osdControlButtonsState | changedButtonMask + : osdControlButtonsState & ~changedButtonMask; + setNewOsdControlButtonState(newButtonState, origEvent); } void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent( - unsigned button, bool up) + unsigned button, bool up, const EventPtr& origEvent) { - osdControlChangeButton(up, - (button & 1) ? 1<<OsdControlEvent::B_BUTTON : 1<<OsdControlEvent::A_BUTTON); + osdControlChangeButton( + up, + ((button & 1) ? (1 << OsdControlEvent::B_BUTTON) + : (1 << OsdControlEvent::A_BUTTON)), + origEvent); } void InputEventGenerator::triggerOsdControlEventsFromKeyEvent( - Keys::KeyCode keyCode, - bool up) + Keys::KeyCode keyCode, bool up, const EventPtr& origEvent) { keyCode = static_cast<Keys::KeyCode>(keyCode & Keys::K_MASK); if (keyCode == Keys::K_LEFT) { - osdControlChangeButton(up, 1<<OsdControlEvent::LEFT_BUTTON); + osdControlChangeButton(up, 1 << OsdControlEvent::LEFT_BUTTON, + origEvent); } else if (keyCode == Keys::K_RIGHT) { - osdControlChangeButton(up, 1<<OsdControlEvent::RIGHT_BUTTON); + osdControlChangeButton(up, 1 << OsdControlEvent::RIGHT_BUTTON, + origEvent); } else if (keyCode == Keys::K_UP) { - osdControlChangeButton(up, 1<<OsdControlEvent::UP_BUTTON); + osdControlChangeButton(up, 1 << OsdControlEvent::UP_BUTTON, + origEvent); } else if (keyCode == Keys::K_DOWN) { - osdControlChangeButton(up, 1<<OsdControlEvent::DOWN_BUTTON); + osdControlChangeButton(up, 1 << OsdControlEvent::DOWN_BUTTON, + origEvent); } else if (keyCode == Keys::K_SPACE || keyCode == Keys::K_RETURN) { - osdControlChangeButton(up, 1<<OsdControlEvent::A_BUTTON); + osdControlChangeButton(up, 1 << OsdControlEvent::A_BUTTON, + origEvent); } else if (keyCode == Keys::K_ESCAPE) { - osdControlChangeButton(up, 1<<OsdControlEvent::B_BUTTON); + osdControlChangeButton(up, 1 << OsdControlEvent::B_BUTTON, + origEvent); } } void InputEventGenerator::handle(const SDL_Event& evt) { - EventDistributor::EventPtr event; - Keys::KeyCode keyCode; + EventPtr event; switch (evt.type) { case SDL_KEYUP: - // Virtual joystick of SDL Android port does not have joystick buttons. - // It has however up to 6 virtual buttons that can be mapped to SDL keyboard - // events. Two of these virtual buttons will be mapped to keys SDLK_WORLD_93 and 94 - // and are interpeted here as joystick buttons (respectively button 0 and 1). + // Virtual joystick of SDL Android port does not have joystick + // buttons. It has however up to 6 virtual buttons that can be + // mapped to SDL keyboard events. Two of these virtual buttons + // will be mapped to keys SDLK_WORLD_93 and 94 and are + // interpeted here as joystick buttons (respectively button 0 + // and 1). if (PLATFORM_ANDROID && evt.key.keysym.sym == SDLK_WORLD_93) { event = make_shared<JoystickButtonUpEvent>(0, 0); - triggerOsdControlEventsFromJoystickButtonEvent(0, true); + triggerOsdControlEventsFromJoystickButtonEvent( + 0, true, event); } else if (PLATFORM_ANDROID && evt.key.keysym.sym == SDLK_WORLD_94) { event = make_shared<JoystickButtonUpEvent>(0, 1); - triggerOsdControlEventsFromJoystickButtonEvent(1, true); + triggerOsdControlEventsFromJoystickButtonEvent( + 1, true, event); } else { - keyCode = Keys::getCode( - evt.key.keysym.sym, - evt.key.keysym.mod, - evt.key.keysym.scancode, - true); - event = make_shared<KeyUpEvent>(keyCode, evt.key.keysym.unicode); - triggerOsdControlEventsFromKeyEvent(keyCode, true); + auto keyCode = Keys::getCode( + evt.key.keysym.sym, evt.key.keysym.mod, + evt.key.keysym.scancode, true); + event = make_shared<KeyUpEvent>( + keyCode, evt.key.keysym.unicode); + triggerOsdControlEventsFromKeyEvent(keyCode, true, event); } break; case SDL_KEYDOWN: if (PLATFORM_ANDROID && evt.key.keysym.sym == SDLK_WORLD_93) { event = make_shared<JoystickButtonDownEvent>(0, 0); - triggerOsdControlEventsFromJoystickButtonEvent(0, false); + triggerOsdControlEventsFromJoystickButtonEvent( + 0, false, event); } else if (PLATFORM_ANDROID && evt.key.keysym.sym == SDLK_WORLD_94) { event = make_shared<JoystickButtonDownEvent>(0, 1); - triggerOsdControlEventsFromJoystickButtonEvent(1, false); + triggerOsdControlEventsFromJoystickButtonEvent( + 1, false, event); } else { - keyCode = Keys::getCode( - evt.key.keysym.sym, - evt.key.keysym.mod, - evt.key.keysym.scancode, - false); - event = make_shared<KeyDownEvent>(keyCode, evt.key.keysym.unicode); - triggerOsdControlEventsFromKeyEvent(keyCode, false); + auto keyCode = Keys::getCode( + evt.key.keysym.sym, evt.key.keysym.mod, + evt.key.keysym.scancode, false); + event = make_shared<KeyDownEvent>( + keyCode, evt.key.keysym.unicode); + triggerOsdControlEventsFromKeyEvent(keyCode, false, event); } break; @@ -403,7 +425,8 @@ int n4 = calcStat4(stat8); for (int i = 0; i < 4; ++i) { if ((o4 ^ n4) & (1 << i)) { - event = createKeyEvent(dirKeys[i], o4 & (1 << i)); + event = createKeyEvent( + dirKeys[i], o4 & (1 << i)); eventDistributor.distributeEvent(event); } } @@ -415,23 +438,23 @@ } #else case SDL_JOYBUTTONUP: - triggerOsdControlEventsFromJoystickButtonEvent( - evt.jbutton.button, true); event = make_shared<JoystickButtonUpEvent>( evt.jbutton.which, evt.jbutton.button); + triggerOsdControlEventsFromJoystickButtonEvent( + evt.jbutton.button, true, event); break; case SDL_JOYBUTTONDOWN: - triggerOsdControlEventsFromJoystickButtonEvent( - evt.jbutton.button, false); event = make_shared<JoystickButtonDownEvent>( evt.jbutton.which, evt.jbutton.button); + triggerOsdControlEventsFromJoystickButtonEvent( + evt.jbutton.button, false, event); break; #endif case SDL_JOYAXISMOTION: event = make_shared<JoystickAxisMotionEvent>( evt.jaxis.which, evt.jaxis.axis, evt.jaxis.value); triggerOsdControlEventsFromJoystickAxisMotion( - evt.jaxis.axis, evt.jaxis.value); + evt.jaxis.axis, evt.jaxis.value, event); break; case SDL_ACTIVEEVENT: Modified: openmsx/trunk/src/events/InputEventGenerator.hh =================================================================== --- openmsx/trunk/src/events/InputEventGenerator.hh 2013-02-06 19:49:18 UTC (rev 13155) +++ openmsx/trunk/src/events/InputEventGenerator.hh 2013-02-07 19:41:03 UTC (rev 13156) @@ -48,6 +48,8 @@ BooleanSetting& getGrabInput() const { return *grabInput; } private: + typedef std::shared_ptr<const Event> EventPtr; + void poll(); void handle(const SDL_Event& event); void setGrabInput(bool grab); @@ -70,11 +72,16 @@ } escapeGrabState; // OsdControl - void setNewOsdControlButtonState(unsigned newState); - void triggerOsdControlEventsFromJoystickAxisMotion(unsigned axis, short value); - void osdControlChangeButton(bool up, unsigned changedButtonMask); - void triggerOsdControlEventsFromJoystickButtonEvent(unsigned button, bool up); - void triggerOsdControlEventsFromKeyEvent(Keys::KeyCode keyCode, bool up); + void setNewOsdControlButtonState( + unsigned newState, const EventPtr& origEvent); + void triggerOsdControlEventsFromJoystickAxisMotion( + unsigned axis, short value, const EventPtr& origEvent); + void osdControlChangeButton( + bool up, unsigned changedButtonMask, const EventPtr& origEvent); + void triggerOsdControlEventsFromJoystickButtonEvent( + unsigned button, bool up, const EventPtr& origEvent); + void triggerOsdControlEventsFromKeyEvent( + Keys::KeyCode keyCode, bool up, const EventPtr& origEvent); #if PLATFORM_GP2X Modified: openmsx/trunk/src/events/InputEvents.cc =================================================================== --- openmsx/trunk/src/events/InputEvents.cc 2013-02-06 19:49:18 UTC (rev 13155) +++ openmsx/trunk/src/events/InputEvents.cc 2013-02-07 19:41:03 UTC (rev 13156) @@ -441,8 +441,10 @@ // class OsdControlEvent -OsdControlEvent::OsdControlEvent(EventType type, unsigned button_) - : TimedEvent(type), button(button_) +OsdControlEvent::OsdControlEvent( + EventType type, unsigned button_, + const std::shared_ptr<const Event>& origEvent_) + : TimedEvent(type), origEvent(origEvent_), button(button_) { } @@ -451,6 +453,11 @@ return button; } +const Event* OsdControlEvent::getOriginalEvent() const +{ + return origEvent.get(); +} + void OsdControlEvent::toStringHelper(TclObject& result) const { result.addListElement("OSDcontrol"); @@ -470,8 +477,9 @@ // class OsdControlReleaseEvent -OsdControlReleaseEvent::OsdControlReleaseEvent(unsigned button) - : OsdControlEvent(OPENMSX_OSD_CONTROL_RELEASE_EVENT, button) +OsdControlReleaseEvent::OsdControlReleaseEvent( + unsigned button, const std::shared_ptr<const Event>& origEvent) + : OsdControlEvent(OPENMSX_OSD_CONTROL_RELEASE_EVENT, button, origEvent) { } @@ -484,8 +492,9 @@ // class OsdControlPressEvent -OsdControlPressEvent::OsdControlPressEvent(unsigned button) - : OsdControlEvent(OPENMSX_OSD_CONTROL_PRESS_EVENT, button) +OsdControlPressEvent::OsdControlPressEvent( + unsigned button, const std::shared_ptr<const Event>& origEvent) + : OsdControlEvent(OPENMSX_OSD_CONTROL_PRESS_EVENT, button, origEvent) { } Modified: openmsx/trunk/src/events/InputEvents.hh =================================================================== --- openmsx/trunk/src/events/InputEvents.hh 2013-02-06 19:49:18 UTC (rev 13155) +++ openmsx/trunk/src/events/InputEvents.hh 2013-02-07 19:41:03 UTC (rev 13156) @@ -6,6 +6,7 @@ #include "openmsx.hh" #include "Event.hh" #include "Keys.hh" +#include <memory> #include <string> #include <vector> @@ -207,6 +208,10 @@ virtual bool lessImpl(const Event& other) const; }; +/** OSD events are triggered by other events. They aggregate keyboard and + * joystick events into one set of events that can be used to e.g. control + * OSD elements. + */ class OsdControlEvent : public TimedEvent { public: @@ -215,19 +220,28 @@ unsigned getButton() const; + /** Get the event that actually triggered the creation of this event. + * Typically this will be a keyboard or joystick event. This could + * also return nullptr (after a toString/fromString conversion). + * For the current use (key-repeat) this is ok. */ + const Event* getOriginalEvent() const; + protected: - OsdControlEvent(EventType type, unsigned button_); + OsdControlEvent(EventType type, unsigned button_, + const std::shared_ptr<const Event>& origEvent); void toStringHelper(TclObject& result) const; private: virtual bool lessImpl(const Event& other) const; + const std::shared_ptr<const Event> origEvent; const unsigned button; }; class OsdControlReleaseEvent : public OsdControlEvent { public: - explicit OsdControlReleaseEvent(unsigned button); + OsdControlReleaseEvent(unsigned button, + const std::shared_ptr<const Event>& origEvent); private: virtual void toStringImpl(TclObject& result) const; }; @@ -235,7 +249,8 @@ class OsdControlPressEvent : public OsdControlEvent { public: - explicit OsdControlPressEvent(unsigned button); + OsdControlPressEvent(unsigned button, + const std::shared_ptr<const Event>& origEvent); private: virtual void toStringImpl(TclObject& result) const; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2013-02-07 20:04:03
|
Revision: 13157 http://openmsx.svn.sourceforge.net/openmsx/?rev=13157&view=rev Author: m9710797 Date: 2013-02-07 20:03:56 +0000 (Thu, 07 Feb 2013) Log Message: ----------- Made all events printable/comparable (fixes crash in debug build) On my laptop (but not on my desktop) a debug build of openMSX would crash soon after startup. The reason was a debug print in InputEventGenerator::handle(). It tried to print an Event object that represented a SDL_VIDEOEXPOSE event. Before this patch not all Event subclasses had a _working_ Event::toString() method (and similar for the <, ==, != operators). This patch does add working implementations. The design was a bit strange: the base Event class offered a toString() method, but some subclasses had an implementation that would do the equivalent of 'assert(false)'. I've replaced those with real implementations. An alternative could have been to introduce an intermediate base class and move the toString() method to that level. (Though for debugging it's useful to be able to print all Events.) Note that while all Events now have a working toString(), it's not yet possible to reconstruct all events from such a string representation. Modified Paths: -------------- openmsx/trunk/src/events/CliConnection.cc openmsx/trunk/src/events/Event.cc openmsx/trunk/src/events/Event.hh openmsx/trunk/src/events/FinishFrameEvent.hh Modified: openmsx/trunk/src/events/CliConnection.cc =================================================================== --- openmsx/trunk/src/events/CliConnection.cc 2013-02-07 19:41:03 UTC (rev 13156) +++ openmsx/trunk/src/events/CliConnection.cc 2013-02-07 20:03:56 UTC (rev 13157) @@ -12,6 +12,7 @@ #include "Event.hh" #include "CommandController.hh" #include "CommandException.hh" +#include "TclObject.hh" #include "XMLElement.hh" #include "checked_cast.hh" #include "cstdiop.hh" @@ -48,6 +49,16 @@ { return id; } + virtual void toStringImpl(TclObject& result) const + { + result.addListElement("CliCmd"); + result.addListElement(getCommand()); + } + virtual bool lessImpl(const Event& other) const + { + auto& otherCmdEvent = checked_cast<const CliCommandEvent&>(other); + return getCommand() < otherCmdEvent.getCommand(); + } private: const string command; const CliConnection* id; Modified: openmsx/trunk/src/events/Event.cc =================================================================== --- openmsx/trunk/src/events/Event.cc 2013-02-07 19:41:03 UTC (rev 13156) +++ openmsx/trunk/src/events/Event.cc 2013-02-07 20:03:56 UTC (rev 13157) @@ -2,7 +2,6 @@ #include "Event.hh" #include "TclObject.hh" -#include "unreachable.hh" namespace openmsx { @@ -45,14 +44,15 @@ return !(*this == other); } -void Event::toStringImpl(TclObject& /*result*/) const +void SimpleEvent::toStringImpl(TclObject& result) const { - UNREACHABLE; + result.addListElement("simple"); + result.addListElement(int(getType())); } -bool Event::lessImpl(const Event& /*other*/) const +bool SimpleEvent::lessImpl(const Event& /*other*/) const { - UNREACHABLE; return false; + return false; } } // namespace openmsx Modified: openmsx/trunk/src/events/Event.hh =================================================================== --- openmsx/trunk/src/events/Event.hh 2013-02-07 19:41:03 UTC (rev 13156) +++ openmsx/trunk/src/events/Event.hh 2013-02-07 20:03:56 UTC (rev 13157) @@ -98,8 +98,8 @@ explicit Event(EventType type); private: - virtual void toStringImpl(TclObject& result) const; - virtual bool lessImpl(const Event& other) const; + virtual void toStringImpl(TclObject& result) const = 0; + virtual bool lessImpl(const Event& other) const = 0; const EventType type; }; @@ -109,6 +109,8 @@ { public: SimpleEvent(EventType type) : Event(type) {} + virtual void toStringImpl(TclObject& result) const; + virtual bool lessImpl(const Event& other) const; }; } // namespace openmsx Modified: openmsx/trunk/src/events/FinishFrameEvent.hh =================================================================== --- openmsx/trunk/src/events/FinishFrameEvent.hh 2013-02-07 19:41:03 UTC (rev 13156) +++ openmsx/trunk/src/events/FinishFrameEvent.hh 2013-02-07 20:03:56 UTC (rev 13157) @@ -5,6 +5,8 @@ #include "Event.hh" #include "VideoSource.hh" +#include "TclObject.hh" +#include "checked_cast.hh" namespace openmsx { @@ -20,6 +22,21 @@ VideoSource getSource() const { return source; } bool isSkipped() const { return skipped; } + virtual void toStringImpl(TclObject& result) const + { + result.addListElement("finishframe"); + result.addListElement(int(source)); + result.addListElement(skipped); + } + virtual bool lessImpl(const Event& other) const + { + auto& ffEv = checked_cast<const FinishFrameEvent&>(other); + return (getSource() != ffEv.getSource()) + ? (getSource() < ffEv.getSource()) + : (isSkipped() < ffEv.isSkipped()); + + } + private: const VideoSource source; const bool skipped; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2013-03-09 12:44:04
|
Revision: 13190 http://openmsx.svn.sourceforge.net/openmsx/?rev=13190&view=rev Author: m9710797 Date: 2013-03-09 12:43:50 +0000 (Sat, 09 Mar 2013) Log Message: ----------- Use unique_ptr iso shared_ptr in AfterCommand In C++98 only copyable smart-pointers could be stored in STL containers. So no std::auto_ptr's, but shared_ptr's were OK. C++11 added move-semantics and this makes it possible to also store unique_ptr's in containers. In the AfterCommand class we had a vector of shared_ptr's. This was only to work around the above limitation (we didn't actually need the shared-ownership stuff). This patch replaces it with cheaper unique_ptr's. Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/AfterCommand.hh Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2013-03-09 12:43:32 UTC (rev 13189) +++ openmsx/trunk/src/events/AfterCommand.cc 2013-03-09 12:43:50 UTC (rev 13190) @@ -17,15 +17,17 @@ #include "StringOp.hh" #include "openmsx.hh" #include "unreachable.hh" +#include "memory.hh" #include <algorithm> +#include <iterator> #include <cstdlib> #include <sstream> using std::ostringstream; using std::string; using std::vector; -using std::shared_ptr; -using std::make_shared; +using std::unique_ptr; +using std::move; namespace openmsx { @@ -40,7 +42,7 @@ protected: AfterCmd(AfterCommand& afterCommand, const TclObject& command); - shared_ptr<AfterCmd> removeSelf(); + unique_ptr<AfterCmd> removeSelf(); AfterCommand& afterCommand; TclObject command; @@ -256,10 +258,10 @@ MSXMotherBoard* motherBoard = reactor.getMotherBoard(); if (!motherBoard) return; double time = getTime(tokens[2]); - auto cmd = make_shared<AfterTimeCmd>( + auto cmd = make_unique<AfterTimeCmd>( motherBoard->getScheduler(), *this, tokens[3], time); - afterCmds.push_back(cmd); result.setString(cmd->getId()); + afterCmds.push_back(move(cmd)); } void AfterCommand::afterRealTime(const vector<TclObject>& tokens, TclObject& result) @@ -268,10 +270,10 @@ throw SyntaxError(); } double time = getTime(tokens[2]); - auto cmd = make_shared<AfterRealTimeCmd>( + auto cmd = make_unique<AfterRealTimeCmd>( *this, tokens[3], time); - afterCmds.push_back(cmd); result.setString(cmd->getId()); + afterCmds.push_back(move(cmd)); } void AfterCommand::afterTclTime( @@ -279,10 +281,10 @@ { TclObject command(tokens.front().getInterpreter()); command.addListElements(tokens.begin() + 2, tokens.end()); - auto cmd = make_shared<AfterRealTimeCmd>( + auto cmd = make_unique<AfterRealTimeCmd>( *this, command, ms / 1000.0); - afterCmds.push_back(cmd); result.setString(cmd->getId()); + afterCmds.push_back(move(cmd)); } template<EventType T> @@ -291,10 +293,10 @@ if (tokens.size() != 3) { throw SyntaxError(); } - auto cmd = make_shared<AfterEventCmd<T>>( + auto cmd = make_unique<AfterEventCmd<T>>( *this, tokens[1], tokens[2]); - afterCmds.push_back(cmd); result.setString(cmd->getId()); + afterCmds.push_back(move(cmd)); } void AfterCommand::afterInputEvent( @@ -303,10 +305,10 @@ if (tokens.size() != 3) { throw SyntaxError(); } - auto cmd = make_shared<AfterInputEventCmd>( + auto cmd = make_unique<AfterInputEventCmd>( *this, event, tokens[2]); - afterCmds.push_back(cmd); result.setString(cmd->getId()); + afterCmds.push_back(move(cmd)); } void AfterCommand::afterIdle(const vector<TclObject>& tokens, TclObject& result) @@ -317,10 +319,10 @@ MSXMotherBoard* motherBoard = reactor.getMotherBoard(); if (!motherBoard) return; double time = getTime(tokens[2]); - auto cmd = make_shared<AfterIdleCmd>( + auto cmd = make_unique<AfterIdleCmd>( motherBoard->getScheduler(), *this, tokens[3], time); - afterCmds.push_back(cmd); result.setString(cmd->getId()); + afterCmds.push_back(move(cmd)); } void AfterCommand::afterInfo(const vector<TclObject>& /*tokens*/, TclObject& result) @@ -397,7 +399,8 @@ { // predicate should return false on matches auto it = partition(afterCmds.begin(), afterCmds.end(), pred); - AfterCmds tmp(it, afterCmds.end()); + AfterCmds tmp(std::make_move_iterator(it), + std::make_move_iterator(afterCmds.end())); afterCmds.erase(it, afterCmds.end()); for (auto& c : tmp) { c->execute(); @@ -405,7 +408,7 @@ } template<EventType T> struct AfterEventPred { - bool operator()(const shared_ptr<AfterCmd>& x) const { + bool operator()(const unique_ptr<AfterCmd>& x) const { return !dynamic_cast<AfterEventCmd<T>*>(x.get()); } }; @@ -415,7 +418,7 @@ } struct AfterTimePred { - bool operator()(const shared_ptr<AfterCmd>& x) const { + bool operator()(const unique_ptr<AfterCmd>& x) const { if (auto* cmd = dynamic_cast<AfterRealTimeCmd*>(x.get())) { if (cmd->hasExpired()) { return false; @@ -426,7 +429,7 @@ }; struct AfterEmuTimePred { - bool operator()(const shared_ptr<AfterCmd>& x) const { + bool operator()(const unique_ptr<AfterCmd>& x) const { if (auto* cmd = dynamic_cast<AfterTimedCmd*>(x.get())) { if (cmd->getTime() == 0.0) { return false; @@ -439,7 +442,7 @@ struct AfterInputEventPred { AfterInputEventPred(const AfterCommand::EventPtr& event_) : event(event_) {} - bool operator()(const shared_ptr<AfterCmd>& x) const { + bool operator()(const unique_ptr<AfterCmd>& x) const { if (auto* cmd = dynamic_cast<AfterInputEventCmd*>(x.get())) { if (*cmd->getEvent() == *event) return false; } @@ -448,7 +451,7 @@ AfterCommand::EventPtr event; }; -int AfterCommand::signalEvent(const shared_ptr<const Event>& event) +int AfterCommand::signalEvent(const std::shared_ptr<const Event>& event) { if (event->getType() == OPENMSX_FINISH_FRAME_EVENT) { executeEvents<OPENMSX_FINISH_FRAME_EVENT>(); @@ -512,12 +515,12 @@ } } -shared_ptr<AfterCmd> AfterCmd::removeSelf() +unique_ptr<AfterCmd> AfterCmd::removeSelf() { for (auto it = afterCommand.afterCmds.begin(); it != afterCommand.afterCmds.end(); ++it) { if (it->get() == this) { - shared_ptr<AfterCmd> result = *it; + auto result = move(*it); afterCommand.afterCmds.erase(it); return result; } Modified: openmsx/trunk/src/events/AfterCommand.hh =================================================================== --- openmsx/trunk/src/events/AfterCommand.hh 2013-03-09 12:43:32 UTC (rev 13189) +++ openmsx/trunk/src/events/AfterCommand.hh 2013-03-09 12:43:50 UTC (rev 13190) @@ -51,7 +51,7 @@ // EventListener virtual int signalEvent(const std::shared_ptr<const Event>& event); - typedef std::vector<std::shared_ptr<AfterCmd>> AfterCmds; + typedef std::vector<std::unique_ptr<AfterCmd>> AfterCmds; AfterCmds afterCmds; Reactor& reactor; EventDistributor& eventDistributor; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2013-03-09 22:10:05
|
Revision: 13195 http://openmsx.svn.sourceforge.net/openmsx/?rev=13195&view=rev Author: m9710797 Date: 2013-03-09 22:09:58 +0000 (Sat, 09 Mar 2013) Log Message: ----------- Fix key-repeat on Android The problem was that OSDControlEvents on Android are generated from joystick events. Now consider the following scenario: - The user presses the virtual d-pad. This e.g. create a host event 'joystick1 axis1 10000'. - This in turn generates e.g. a 'OSDControl cursor up pressed' event. - When something was bound to this event, that action gets executed. When it was bound with the '-repeat' flag, we also start a timer to re-trigger the action later. - Now the problem: because it's impossible to keep an analogue joystick perfectly still, it's very likely that soon after the first host event is send, there is a new host event, e.g. 'joystick axis1 10027'. - Because this new event is not the same as the to-be repeated event, the repeat process is canceled. (The events is also not the same as the original host event that generated the OSDControl event, this hack was added in revision 13156). This patch adds a more general mechanism to decide which events should cancel another repeating event. And specifically: joystick axis events don't cancel each other anymore. See comments in the code for more details. Revision Links: -------------- http://openmsx.svn.sourceforge.net/openmsx/?rev=13156&view=rev Modified Paths: -------------- openmsx/trunk/src/events/Event.hh openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/InputEvents.cc openmsx/trunk/src/events/InputEvents.hh Modified: openmsx/trunk/src/events/Event.hh =================================================================== --- openmsx/trunk/src/events/Event.hh 2013-03-09 21:21:53 UTC (rev 13194) +++ openmsx/trunk/src/events/Event.hh 2013-03-09 22:09:58 UTC (rev 13195) @@ -97,6 +97,13 @@ bool operator==(const Event& other) const; bool operator!=(const Event& other) const; + /** Should 'bind -repeat' be stopped by 'other' event. + * Normally all events should stop auto-repeat of the previous + * event. But see OsdControlEvent for some exceptions. */ + virtual bool isRepeatStopper(const Event& /*other*/) const { + return true; + } + protected: explicit Event(EventType type); Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2013-03-09 21:21:53 UTC (rev 13194) +++ openmsx/trunk/src/events/HotKey.cc 2013-03-09 22:09:58 UTC (rev 13195) @@ -371,14 +371,9 @@ // a corresponding osd event (the osd event is send before the // original event). Without this hack, key-repeat will not work // for osd key bindings. - bool stop = true; - if (auto osdEv = dynamic_cast<const OsdControlEvent*>( - lastEvent.get())) { - if (osdEv->getOriginalEvent() == event.get()) { - stop = false; - } + if (lastEvent.get() && lastEvent->isRepeatStopper(*event)) { + stopRepeat(); } - if (stop) stopRepeat(); } // First search in active layers (from back to front) @@ -427,7 +422,15 @@ // I initially thought about using the builtin SDL key-repeat feature, // but that won't work for example on joystick buttons. So we have to // code it ourselves. - unsigned delay = (lastEvent.get() ? 30 : 500) * 1000; + + // On android, because of the sensitivity of the touch screen it's + // very hard to have touches of short durations. So half a second is + // too short for the key-repeat-delay. A full second should be fine. + static const unsigned DELAY = PLATFORM_ANDROID ? 1000 : 500; + // Repeat period. + static const unsigned PERIOD = 30; + + unsigned delay = (lastEvent.get() ? PERIOD : DELAY) * 1000; lastEvent = event; repeatAlarm->schedule(delay); } Modified: openmsx/trunk/src/events/InputEvents.cc =================================================================== --- openmsx/trunk/src/events/InputEvents.cc 2013-03-09 21:21:53 UTC (rev 13194) +++ openmsx/trunk/src/events/InputEvents.cc 2013-03-09 22:09:58 UTC (rev 13195) @@ -453,9 +453,20 @@ return button; } -const Event* OsdControlEvent::getOriginalEvent() const +bool OsdControlEvent::isRepeatStopper(const Event& other) const { - return origEvent.get(); + // If this OsdControlEvent was geneated by the other event, then + // repeat should not be stopped. + if (origEvent.get() == &other) return false; + + // If this OsdControlEvent event was generated by a joystick motion + // event and the new event is also a joystick motion event then don't + // stop repeat. We don't need to check the actual values of the events + // (it also isn't trivial), because when the values differ by enough, + // a new OsdControlEvent will be generated and that one will stop + // repeat. + return !dynamic_cast<const JoystickAxisMotionEvent*>(origEvent.get()) || + !dynamic_cast<const JoystickAxisMotionEvent*>(&other); } void OsdControlEvent::toStringHelper(TclObject& result) const Modified: openmsx/trunk/src/events/InputEvents.hh =================================================================== --- openmsx/trunk/src/events/InputEvents.hh 2013-03-09 21:21:53 UTC (rev 13194) +++ openmsx/trunk/src/events/InputEvents.hh 2013-03-09 22:09:58 UTC (rev 13195) @@ -224,7 +224,14 @@ * Typically this will be a keyboard or joystick event. This could * also return nullptr (after a toString/fromString conversion). * For the current use (key-repeat) this is ok. */ - const Event* getOriginalEvent() const; + /** Normally all events should stop the repeat process in 'bind -repeat', + * but in case of OsdControlEvent there are two exceptions: + * - we should not stop because of the original host event that + * actually generated this 'artificial' OsdControlEvent. + * - if the original host event is a joystick motion event, we + * should not stop repeat for 'small' relative new joystick events. + */ + virtual bool isRepeatStopper(const Event& other) const; protected: OsdControlEvent(EventType type, unsigned button_, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2013-03-12 20:36:20
|
Revision: 13201 http://openmsx.svn.sourceforge.net/openmsx/?rev=13201&view=rev Author: m9710797 Date: 2013-03-12 20:36:11 +0000 (Tue, 12 Mar 2013) Log Message: ----------- Made it possible to 'bind' or 'after' 'mouse motion' This patch makes it possible to do: bind "mouse motion" { do some stuff } after "mouse motion" { do some stuff } Before it was only possible to use 'after' on a specific mouse motion event (like 'mouse motion 123 -456), but that's of course not very practical. Using 'bind' for such specific events was not (and still is not) possible. One of the following patches will use this new feature to improve the OSD menu (Android touch events are shown as mouse events by SDL). Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/Event.hh openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/HotKey.hh openmsx/trunk/src/events/InputEventFactory.cc openmsx/trunk/src/events/InputEvents.cc openmsx/trunk/src/events/InputEvents.hh Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/AfterCommand.cc 2013-03-12 20:36:11 UTC (rev 13201) @@ -444,7 +444,7 @@ : event(event_) {} bool operator()(const unique_ptr<AfterCmd>& x) const { if (auto* cmd = dynamic_cast<AfterInputEventCmd*>(x.get())) { - if (*cmd->getEvent() == *event) return false; + if (cmd->getEvent()->matches(*event)) return false; } return true; } Modified: openmsx/trunk/src/events/Event.hh =================================================================== --- openmsx/trunk/src/events/Event.hh 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/Event.hh 2013-03-12 20:36:11 UTC (rev 13201) @@ -15,6 +15,7 @@ OPENMSX_KEY_UP_EVENT, OPENMSX_KEY_DOWN_EVENT, OPENMSX_MOUSE_MOTION_EVENT, + OPENMSX_MOUSE_MOTION_GROUP_EVENT, OPENMSX_MOUSE_BUTTON_UP_EVENT, OPENMSX_MOUSE_BUTTON_DOWN_EVENT, OPENMSX_JOY_AXIS_MOTION_EVENT, @@ -104,6 +105,13 @@ return true; } + /** Does this event 'match' the given event. Normally an event + * only matches itself (as defined by operator==). But e.g. + * MouseMotionGroupEvent matches any MouseMotionEvent. */ + virtual bool matches(const Event& other) const { + return *this == other; + } + protected: explicit Event(EventType type); Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/HotKey.cc 2013-03-12 20:36:11 UTC (rev 13201) @@ -112,6 +112,8 @@ eventDistributor.registerEventListener( OPENMSX_KEY_UP_EVENT, *this, EventDistributor::HOTKEY); eventDistributor.registerEventListener( + OPENMSX_MOUSE_MOTION_EVENT, *this, EventDistributor::HOTKEY); + eventDistributor.registerEventListener( OPENMSX_MOUSE_BUTTON_DOWN_EVENT, *this, EventDistributor::HOTKEY); eventDistributor.registerEventListener( OPENMSX_MOUSE_BUTTON_UP_EVENT, *this, EventDistributor::HOTKEY); @@ -139,6 +141,7 @@ eventDistributor.unregisterEventListener(OPENMSX_JOY_AXIS_MOTION_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_MOUSE_BUTTON_UP_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_MOUSE_BUTTON_DOWN_EVENT, *this); + eventDistributor.unregisterEventListener(OPENMSX_MOUSE_MOTION_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_KEY_UP_EVENT, *this); eventDistributor.unregisterEventListener(OPENMSX_KEY_DOWN_EVENT, *this); } @@ -209,11 +212,12 @@ static HotKey::EventPtr createEvent(const string& str) { auto event = InputEventFactory::createInputEvent(str); - if (!dynamic_cast<const KeyEvent*> (event.get()) && - !dynamic_cast<const MouseButtonEvent*>(event.get()) && - !dynamic_cast<const JoystickEvent*> (event.get()) && - !dynamic_cast<const OsdControlEvent*> (event.get()) && - !dynamic_cast<const FocusEvent*> (event.get())) { + if (!dynamic_cast<const KeyEvent*> (event.get()) && + !dynamic_cast<const MouseButtonEvent*> (event.get()) && + !dynamic_cast<const MouseMotionGroupEvent*>(event.get()) && + !dynamic_cast<const JoystickEvent*> (event.get()) && + !dynamic_cast<const OsdControlEvent*> (event.get()) && + !dynamic_cast<const FocusEvent*> (event.get())) { throw CommandException("Unsupported event type"); } return event; @@ -355,6 +359,15 @@ } } +static HotKey::BindMap::const_iterator findMatch( + const HotKey::BindMap& map, const Event& event) +{ + return find_if(map.begin(), map.end(), + [&](const HotKey::BindMap::value_type& p) { + return p.first->matches(event); + }); +} + int HotKey::signalEvent(const EventPtr& event_) { // Convert special 'repeat' event into the actual to-be-repeated event. @@ -380,7 +393,7 @@ bool blocking = false; for (auto it = activeLayers.rbegin(); it != activeLayers.rend(); ++it) { auto& cmap = layerMap[it->layer]; // ok, if this entry doesn't exist yet - auto it2 = cmap.find(event); + auto it2 = findMatch(cmap, *event); if (it2 != cmap.end()) { executeBinding(event, it2->second); // Deny event to MSX listeners, also don't pass event @@ -392,7 +405,7 @@ } // If the event was not yet handled, try the default layer. - auto it = cmdMap.find(event); + auto it = findMatch(cmdMap, *event); if (it != cmdMap.end()) { executeBinding(event, it->second); return EventDistributor::MSX; // deny event to MSX listeners Modified: openmsx/trunk/src/events/HotKey.hh =================================================================== --- openmsx/trunk/src/events/HotKey.hh 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/HotKey.hh 2013-03-12 20:36:11 UTC (rev 13201) @@ -31,7 +31,17 @@ class HotKey : public EventListener, private noncopyable { public: + struct HotKeyInfo { + HotKeyInfo() {} // for map::operator[] + HotKeyInfo(const std::string& command_, bool repeat_ = false) + : command(command_), repeat(repeat_) {} + std::string command; + bool repeat; + }; typedef std::shared_ptr<const Event> EventPtr; + typedef std::map<EventPtr, HotKeyInfo, deref_less<EventPtr>> BindMap; + typedef std::set<EventPtr, deref_less<EventPtr>> KeySet; + HotKey(GlobalCommandController& commandController, EventDistributor& eventDistributor); virtual ~HotKey(); @@ -40,19 +50,10 @@ void saveBindings(XMLElement& config) const; private: - struct HotKeyInfo { - HotKeyInfo() {} // for map::operator[] - HotKeyInfo(const std::string& command_, bool repeat_ = false) - : command(command_), repeat(repeat_) {} - std::string command; - bool repeat; - }; struct LayerInfo { std::string layer; bool blocking; }; - typedef std::map<EventPtr, HotKeyInfo, deref_less<EventPtr>> BindMap; - typedef std::set<EventPtr, deref_less<EventPtr>> KeySet; void initDefaultBindings(); void bind (const EventPtr& event, const HotKeyInfo& info); Modified: openmsx/trunk/src/events/InputEventFactory.cc =================================================================== --- openmsx/trunk/src/events/InputEventFactory.cc 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/InputEventFactory.cc 2013-03-12 20:36:11 UTC (rev 13201) @@ -60,6 +60,9 @@ throw CommandException("Invalid mouse event: " + str); } if (components[1] == "motion") { + if (components.size() == 2) { + return make_shared<MouseMotionGroupEvent>(); + } if (components.size() != 4) { throw CommandException("Invalid mouse motion event: " + str); } Modified: openmsx/trunk/src/events/InputEvents.cc =================================================================== --- openmsx/trunk/src/events/InputEvents.cc 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/InputEvents.cc 2013-03-12 20:36:11 UTC (rev 13201) @@ -250,6 +250,31 @@ } +// class MouseMotionGroupEvent : public Event + +MouseMotionGroupEvent::MouseMotionGroupEvent() + : Event(OPENMSX_MOUSE_MOTION_GROUP_EVENT) +{ +} + +void MouseMotionGroupEvent::toStringImpl(TclObject& result) const +{ + result.addListElement("mouse"); + result.addListElement("motion"); +} + +bool MouseMotionGroupEvent::lessImpl(const Event& /*other*/) const +{ + // All MouseMotionGroup events are equivalent + return false; +} + +bool MouseMotionGroupEvent::matches(const Event& other) const +{ + return other.getType() == OPENMSX_MOUSE_MOTION_EVENT; +} + + // class JoystickEvent JoystickEvent::JoystickEvent(EventType type, unsigned joystick_) Modified: openmsx/trunk/src/events/InputEvents.hh =================================================================== --- openmsx/trunk/src/events/InputEvents.hh 2013-03-12 20:34:38 UTC (rev 13200) +++ openmsx/trunk/src/events/InputEvents.hh 2013-03-12 20:36:11 UTC (rev 13201) @@ -105,7 +105,18 @@ const int yrel; }; +class MouseMotionGroupEvent : public Event +{ +public: + MouseMotionGroupEvent(); +private: + virtual void toStringImpl(TclObject& result) const; + virtual bool lessImpl(const Event& other) const; + virtual bool matches(const Event& other) const; +}; + + class JoystickEvent : public TimedEvent { public: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2012-12-01 15:09:07
|
Revision: 13000 http://openmsx.svn.sourceforge.net/openmsx/?rev=13000&view=rev Author: m9710797 Date: 2012-12-01 15:09:00 +0000 (Sat, 01 Dec 2012) Log Message: ----------- [2/4] Implement input layer system: c++ part As already mentioned in the previous patch, the input layer system is a cleaner solution for the hack we introduced in revision 12986. The problem that this hack solved was the following: Revision 12986 introduced the 'OSDControl events', these are abstract events that will typically be used to control OSD elements (like the OSD keyboard or menu). These events e.g. aggregate the cursor and all joystick movement events into abstract movement events. So the OSD widgets can use these abstract events instead of having to listen to all possible movement events (and similar for action buttons). There was however one problem with this approach: for example the OSD keyboard widget is now bound to 'OSDControl up/down/left/right' events instead of (as before) directly to the cursor key events. So the cursor key events are no longer bound. A consequence of this is that these events are also no longer blocked from the MSX (the HotKey class doesn't 'consume' the event anymore). So while using the OSD keyboard (with the cursor keys), the MSX also receives events for those keys, making entering text with the OSD keyboard impossible. As a temporary hack, we blocked all events to the emulated MSX as soon as at least one OSDControl event was bound (so e.g. when the OSD keyboard was active). The above hack works fine for the combination OSD-keyboard/emulated-MSX, but more general, when there are multiple OSD widgets, those widgets may also want to block events from each other. Or in other words, at some point a widget may want to have (semi-)exclusive access to the events. This patch series implements an 'input layer system'. Tcl scripts can now instead of globally binding commands to events (e.g. hotkeys) bind events to a specific input layer. Later such a layer can be activated (and deactivated). An active layer can be in blocking or non-blocking mode. Blocking mode means that even if an event is not used by the current layer, the event will not be passed to the lower layer or to the emulated MSX (it will still be passed to the globally bound hotkeys). Very briefly, the (un)bind command now takes an optional -layer option. And there are two new commands {de}activate_input_layer to (de)activate the layers, the activate command takes an optional -blocking flag. See next patch for a more detailed description of the commands. Revision Links: -------------- http://openmsx.svn.sourceforge.net/openmsx/?rev=12986&view=rev http://openmsx.svn.sourceforge.net/openmsx/?rev=12986&view=rev Modified Paths: -------------- openmsx/trunk/src/events/HotKey.cc openmsx/trunk/src/events/HotKey.hh Modified: openmsx/trunk/src/events/HotKey.cc =================================================================== --- openmsx/trunk/src/events/HotKey.cc 2012-12-01 15:08:43 UTC (rev 12999) +++ openmsx/trunk/src/events/HotKey.cc 2012-12-01 15:09:00 UTC (rev 13000) @@ -9,16 +9,25 @@ #include "CliComm.hh" #include "InputEvents.hh" #include "XMLElement.hh" +#include "TclObject.hh" #include "SettingsConfig.hh" #include "AlarmEvent.hh" #include "memory.hh" #include "unreachable.hh" +#include <algorithm> #include <cassert> using std::string; using std::vector; using std::make_shared; +// This file implements all Tcl key bindings. These are the 'classical' hotkeys +// (e.g. F11 to (un)mute sound) and the more recent input layers. The idea +// behind an input layer is something like an OSD widget that (temporarily) +// takes semi-exclusive access to the input. So while the widget is active +// keyboard (and joystick) input is no longer passed to the emulated MSX. +// However the classical hotkeys or the openMSX console still receive input. + namespace openmsx { const bool META_HOT_KEYS = @@ -54,7 +63,27 @@ const bool defaultCmd; }; +class ActivateCmd : public Command +{ +public: + ActivateCmd(CommandController& commandController, HotKey& hotKey); + virtual string execute(const vector<string>& tokens); + virtual string help(const vector<string>& tokens) const; +private: + HotKey& hotKey; +}; +class DeactivateCmd : public Command +{ +public: + DeactivateCmd(CommandController& commandController, HotKey& hotKey); + virtual string execute(const vector<string>& tokens); + virtual string help(const vector<string>& tokens) const; +private: + HotKey& hotKey; +}; + + HotKey::HotKey(GlobalCommandController& commandController_, EventDistributor& eventDistributor_) : bindCmd(make_unique<BindCmd>( @@ -65,6 +94,10 @@ commandController_, *this, true)) , unbindDefaultCmd(make_unique<UnbindCmd>( commandController_, *this, true)) + , activateCmd(make_unique<ActivateCmd>( + commandController_, *this)) + , deactivateCmd(make_unique<DeactivateCmd>( + commandController_, *this)) , repeatAlarm(make_unique<AlarmEvent>( eventDistributor_, *this, OPENMSX_REPEAT_HOTKEY, EventDistributor::HOTKEY)) @@ -273,8 +306,49 @@ defaultMap.erase(event); } +void HotKey::bindLayer(const EventPtr& event, const HotKeyInfo& info, + const string& layer) +{ + layerMap[layer][event] = info; +} + +void HotKey::unbindLayer(const EventPtr& event, const string& layer) +{ + layerMap[layer].erase(event); +} + +void HotKey::unbindFullLayer(const string& layer) +{ + layerMap.erase(layer); +} + +void HotKey::activateLayer(const std::string& layer, bool blocking) +{ + // Insert new activattion record at the end of the list. + // (it's not an error if the same layer was already active, in such + // as case it will now appear twice in the list of active layer, + // and it must also be deactivated twice). + LayerInfo info; + info.layer = layer; + info.blocking = blocking; + activeLayers.push_back(info); +} + +void HotKey::deactivateLayer(const std::string& layer) +{ + // remove the first matching activation record from the end + // (it's not an error if there is no match at all) + auto it = find_if(activeLayers.rbegin(), activeLayers.rend(), + [&](const LayerInfo& info) { return info.layer == layer; }); + if (it != activeLayers.rend()) { + // 'reverse_iterator' -> 'iterator' conversion is a bit tricky + activeLayers.erase((it + 1).base()); + } +} + int HotKey::signalEvent(const EventPtr& event_) { + // Convert special 'repeat' event into the actual to-be-repeated event. EventPtr event = event_; if (event->getType() == OPENMSX_REPEAT_HOTKEY) { if (!lastEvent.get()) return true; @@ -282,11 +356,36 @@ } else if (lastEvent.get() && (*lastEvent != *event)) { stopRepeat(); } + + // First search in active layers (from back to front) + bool blocking = false; + for (auto it = activeLayers.rbegin(); it != activeLayers.rend(); ++it) { + auto& cmap = layerMap[it->layer]; // ok, if this entry doesn't exist yet + auto it2 = cmap.find(event); + if (it2 != cmap.end()) { + executeBinding(event, it2->second); + // Deny event to MSX listeners, also don't pass event + // to other layers (including the default layer). + return EventDistributor::MSX; + } + blocking = it->blocking; + if (blocking) break; // don't try lower layers + } + + // If the event was not yet handled, try the default layer. auto it = cmdMap.find(event); - if (it == cmdMap.end()) { - return 0; + if (it != cmdMap.end()) { + executeBinding(event, it->second); + return EventDistributor::MSX; // deny event to MSX listeners } - const HotKeyInfo& info = it->second; + + // Event is not handled, only let it pass to the MSX if there was no + // blocking layer active. + return blocking ? EventDistributor::MSX : 0; +} + +void HotKey::executeBinding(const EventPtr& event, const HotKeyInfo& info) +{ if (info.repeat) { startRepeat(event); } @@ -297,7 +396,6 @@ commandController.getCliComm().printWarning( "Error executing hot key command: " + e.getMessage()); } - return EventDistributor::MSX; // deny event to MSX listeners } void HotKey::startRepeat(const EventPtr& event) @@ -334,27 +432,74 @@ string BindCmd::formatBinding(HotKey::BindMap::const_iterator it) { - const HotKey::HotKeyInfo& info = it->second; + auto& info = it->second; return it->first->toString() + (info.repeat ? " [repeat]" : "") + ": " + info.command + '\n'; } -string BindCmd::execute(const vector<string>& tokens) +static vector<string> parse(bool defaultCmd, vector<string> tokens, + string& layer, bool& layers) { - HotKey::BindMap& cmdMap = defaultCmd ? hotKey.defaultMap - : hotKey.cmdMap; + layers = false; + for (size_t i = 1; i < tokens.size(); /**/) { + if (tokens[i] == "-layer") { + if (i == (tokens.size() - 1)) { + throw CommandException("Missing layer name"); + } + if (defaultCmd) { + throw CommandException( + "Layers are not supported for default bindings"); + } + layer = tokens[i + 1]; + + auto it = tokens.begin() + i; + tokens.erase(it, it + 2); + } else if (tokens[i] == "-layers") { + layers = true; + tokens.erase(tokens.begin() + i); + } else { + ++i; + } + } + return tokens; +} + +string BindCmd::execute(const vector<string>& tokens_) +{ + string layer; + bool layers; + auto tokens = parse(defaultCmd, tokens_, layer, layers); + + auto& cmdMap = defaultCmd + ? hotKey.defaultMap + : layer.empty() ? hotKey.cmdMap + : hotKey.layerMap[layer]; + + if (layers) { + TclObject result; + for (auto it = hotKey.layerMap.begin(); + it != hotKey.layerMap.end(); ++it) { + // An alternative for this test is to always properly + // prune layerMap. ATM this approach seems simpler. + if (!it->second.empty()) { + result.addListElement(it->first); + } + } + return result.getString().str(); + } + string result; switch (tokens.size()) { case 0: UNREACHABLE; case 1: - // show all bounded keys + // show all bounded keys (for this layer) for (auto it = cmdMap.begin(); it != cmdMap.end(); ++it) { result += formatBinding(it); } break; case 2: { - // show bindings for this key + // show bindings for this key (in this layer) auto it = cmdMap.find(createEvent(tokens[1])); if (it == cmdMap.end()) { throw CommandException("Key not bound"); @@ -376,10 +521,13 @@ command += tokens[i]; } HotKey::HotKeyInfo info(command, repeat); + auto event = createEvent(tokens[1]); if (defaultCmd) { - hotKey.bindDefault(createEvent(tokens[1]), info); + hotKey.bindDefault(event, info); + } else if (layer.empty()) { + hotKey.bind(event, info); } else { - hotKey.bind (createEvent(tokens[1]), info); + hotKey.bindLayer(event, info, layer); } break; } @@ -391,7 +539,11 @@ string cmd = getBindCmdName(defaultCmd); return cmd + " : show all bounded keys\n" + cmd + " <key> : show binding for this key\n" + - cmd + " <key> [-repeat] <cmd> : bind key to command, optionally repeat command while key remains pressed\n"; + cmd + " <key> [-repeat] <cmd> : bind key to command, optionally " + "repeat command while key remains pressed\n" + "These 3 take an optional '-layer <layername>' option, " + "see activate_input_layer." + + cmd + " -layers : show a list of layers with bound keys\n"; } @@ -410,22 +562,116 @@ { } -string UnbindCmd::execute(const vector<string>& tokens) +string UnbindCmd::execute(const vector<string>& tokens_) { - if (tokens.size() != 2) { + string layer; + bool layers; + auto tokens = parse(defaultCmd, tokens_, layer, layers); + if (layers) { throw SyntaxError(); } + if ((tokens.size() > 2) || (layer.empty() && (tokens.size() != 2))) { + throw SyntaxError(); + } + + HotKey::EventPtr event; + if (tokens.size() == 2) { + event = createEvent(tokens[1]); + } + if (defaultCmd) { - hotKey.unbindDefault(createEvent(tokens[1])); + assert(event); + hotKey.unbindDefault(event); + } else if (layer.empty()) { + assert(event); + hotKey.unbind(event); } else { - hotKey.unbind (createEvent(tokens[1])); + if (event) { + hotKey.unbindLayer(event, layer); + } else { + hotKey.unbindFullLayer(layer); + } } return ""; } string UnbindCmd::help(const vector<string>& /*tokens*/) const { string cmd = getUnbindCmdName(defaultCmd); - return cmd + " <key> : unbind this key\n"; + return cmd + " <key> : unbind this key\n" + + cmd + " -layer <layername> <key> : unbind key in a specific layer\n" + + cmd + " -layer <layername> : unbind all keys in this layer\n"; } + +// class ActivateCmd + +ActivateCmd::ActivateCmd(CommandController& commandController, HotKey& hotKey_) + : Command(commandController, "activate_input_layer") + , hotKey(hotKey_) +{ +} + +string ActivateCmd::execute(const vector<string>& tokens) +{ + string layer; + bool blocking = false; + for (size_t i = 1; i < tokens.size(); ++i) { + if (tokens[i] == "-blocking") { + blocking = true; + } else { + if (!layer.empty()) { + throw SyntaxError(); + } + layer = tokens[i]; + } + } + + string result; + if (layer.empty()) { + for (auto it = hotKey.activeLayers.rbegin(); + it != hotKey.activeLayers.rend(); ++it) { + result += it->layer; + if (it->blocking) { + result += " -blocking"; + } + result += '\n'; + } + } else { + hotKey.activateLayer(layer, blocking); + } + return result; +} + +string ActivateCmd::help(const vector<string>& /*tokens*/) const +{ + return "activate_input_layer " + ": show list of active layers (most recent on top)\n" + "activate_input_layer [-blocking] <layername> " + ": activate new layer, optionally in blocking mode\n"; +} + + +// class DeactivateCmd + +DeactivateCmd::DeactivateCmd(CommandController& commandController, HotKey& hotKey_) + : Command(commandController, "deactivate_input_layer") + , hotKey(hotKey_) +{ +} + +string DeactivateCmd::execute(const vector<string>& tokens) +{ + if (tokens.size() != 2) { + throw SyntaxError(); + } + hotKey.deactivateLayer(tokens[1]); + return ""; +} + +string DeactivateCmd::help(const vector<string>& /*tokens*/) const +{ + return "deactivate_input_layer <layername> : deactive the given input layer"; +} + + } // namespace openmsx Modified: openmsx/trunk/src/events/HotKey.hh =================================================================== --- openmsx/trunk/src/events/HotKey.hh 2012-12-01 15:08:43 UTC (rev 12999) +++ openmsx/trunk/src/events/HotKey.hh 2012-12-01 15:09:00 UTC (rev 13000) @@ -8,6 +8,7 @@ #include "noncopyable.hh" #include <map> #include <set> +#include <vector> #include <string> #include <memory> @@ -18,6 +19,8 @@ class XMLElement; class BindCmd; class UnbindCmd; +class ActivateCmd; +class DeactivateCmd; class AlarmEvent; template<typename T> struct deref_less @@ -44,6 +47,10 @@ std::string command; bool repeat; }; + struct LayerInfo { + std::string layer; + bool blocking; + }; typedef std::map<EventPtr, HotKeyInfo, deref_less<EventPtr>> BindMap; typedef std::set<EventPtr, deref_less<EventPtr>> KeySet; @@ -52,6 +59,14 @@ void unbind (const EventPtr& event); void bindDefault (const EventPtr& event, const HotKeyInfo& info); void unbindDefault(const EventPtr& event); + void bindLayer (const EventPtr& event, const HotKeyInfo& info, + const std::string& layer); + void unbindLayer (const EventPtr& event, const std::string& layer); + void unbindFullLayer(const std::string& layer); + void activateLayer (const std::string& layer, bool blocking); + void deactivateLayer(const std::string& layer); + + void executeBinding(const EventPtr& event, const HotKeyInfo& info); void startRepeat (const EventPtr& event); void stopRepeat(); @@ -60,14 +75,20 @@ friend class BindCmd; friend class UnbindCmd; - const std::unique_ptr<BindCmd> bindCmd; - const std::unique_ptr<UnbindCmd> unbindCmd; - const std::unique_ptr<BindCmd> bindDefaultCmd; - const std::unique_ptr<UnbindCmd> unbindDefaultCmd; - const std::unique_ptr<AlarmEvent> repeatAlarm; + friend class ActivateCmd; + friend class DeactivateCmd; + const std::unique_ptr<BindCmd> bindCmd; + const std::unique_ptr<UnbindCmd> unbindCmd; + const std::unique_ptr<BindCmd> bindDefaultCmd; + const std::unique_ptr<UnbindCmd> unbindDefaultCmd; + const std::unique_ptr<ActivateCmd> activateCmd; + const std::unique_ptr<DeactivateCmd> deactivateCmd; + const std::unique_ptr<AlarmEvent> repeatAlarm; BindMap cmdMap; BindMap defaultMap; + std::map<std::string, BindMap> layerMap; + std::vector<LayerInfo> activeLayers; KeySet boundKeys; KeySet unboundKeys; GlobalCommandController& commandController; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <m97...@us...> - 2013-03-09 12:43:39
|
Revision: 13189 http://openmsx.svn.sourceforge.net/openmsx/?rev=13189&view=rev Author: m9710797 Date: 2013-03-09 12:43:32 +0000 (Sat, 09 Mar 2013) Log Message: ----------- Fixed assert on 'after time 5 reset' After-emutime scheduled commands are executed at an exact emutime. This could also be e.g. in the middle of a Z80 instruction. Some commands, like 'reset' couldn't handle this and they trigger an assert. Actually if the assert in the reset command is removed, everything does work as it should. I also can't immediately think of any other command that will go wrong when executed in the middle of an instruction. Though instead of removing the assert, I decided to postpone the command till the next instruction boundary. This makes it much easier to reason about the correctness of the code. Modified Paths: -------------- openmsx/trunk/src/events/AfterCommand.cc openmsx/trunk/src/events/AfterCommand.hh openmsx/trunk/src/events/Event.hh Modified: openmsx/trunk/src/events/AfterCommand.cc =================================================================== --- openmsx/trunk/src/events/AfterCommand.cc 2013-03-09 12:43:11 UTC (rev 13188) +++ openmsx/trunk/src/events/AfterCommand.cc 2013-03-09 12:43:32 UTC (rev 13189) @@ -41,7 +41,7 @@ AfterCmd(AfterCommand& afterCommand, const TclObject& command); shared_ptr<AfterCmd> removeSelf(); -private: + AfterCommand& afterCommand; TclObject command; string id; @@ -61,7 +61,8 @@ virtual void executeUntil(EmuTime::param time, int userData); virtual void schedulerDeleted(); - double time; + double time; // Zero when expired, otherwise the original duration (to + // be able to reschedule for 'after idle'). }; class AfterTimeCmd : public AfterTimedCmd @@ -110,7 +111,6 @@ { public: AfterRealTimeCmd(AfterCommand& afterCommand, - EventDistributor& eventDistributor, const TclObject& command, double time); virtual ~AfterRealTimeCmd(); virtual string getType() const; @@ -119,7 +119,6 @@ private: virtual bool alarm(); - EventDistributor& eventDistributor; bool expired; }; @@ -161,11 +160,15 @@ OPENMSX_MACHINE_LOADED_EVENT, *this); eventDistributor.registerEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); + eventDistributor.registerEventListener( + OPENMSX_AFTER_TIMED_EVENT, *this); } AfterCommand::~AfterCommand() { eventDistributor.unregisterEventListener( + OPENMSX_AFTER_TIMED_EVENT, *this); + eventDistributor.unregisterEventListener( OPENMSX_AFTER_REALTIME_EVENT, *this); eventDistributor.unregisterEventListener( OPENMSX_MACHINE_LOADED_EVENT, *this); @@ -266,7 +269,7 @@ } double time = getTime(tokens[2]); auto cmd = make_shared<AfterRealTimeCmd>( - *this, eventDistributor, tokens[3], time); + *this, tokens[3], time); afterCmds.push_back(cmd); result.setString(cmd->getId()); } @@ -277,7 +280,7 @@ TclObject command(tokens.front().getInterpreter()); command.addListElements(tokens.begin() + 2, tokens.end()); auto cmd = make_shared<AfterRealTimeCmd>( - *this, eventDistributor, command, ms / 1000.0); + *this, command, ms / 1000.0); afterCmds.push_back(cmd); result.setString(cmd->getId()); } @@ -413,7 +416,7 @@ struct AfterTimePred { bool operator()(const shared_ptr<AfterCmd>& x) const { - if (auto cmd = dynamic_cast<AfterRealTimeCmd*>(x.get())) { + if (auto* cmd = dynamic_cast<AfterRealTimeCmd*>(x.get())) { if (cmd->hasExpired()) { return false; } @@ -421,16 +424,23 @@ return true; } }; -void AfterCommand::executeRealTime() -{ - executeMatches(AfterTimePred()); -} +struct AfterEmuTimePred { + bool operator()(const shared_ptr<AfterCmd>& x) const { + if (auto* cmd = dynamic_cast<AfterTimedCmd*>(x.get())) { + if (cmd->getTime() == 0.0) { + return false; + } + } + return true; + } +}; + struct AfterInputEventPred { AfterInputEventPred(const AfterCommand::EventPtr& event_) : event(event_) {} bool operator()(const shared_ptr<AfterCmd>& x) const { - if (auto cmd = dynamic_cast<AfterInputEventCmd*>(x.get())) { + if (auto* cmd = dynamic_cast<AfterInputEventCmd*>(x.get())) { if (*cmd->getEvent() == *event) return false; } return true; @@ -451,7 +461,9 @@ } else if (event->getType() == OPENMSX_MACHINE_LOADED_EVENT) { executeEvents<OPENMSX_MACHINE_LOADED_EVENT>(); } else if (event->getType() == OPENMSX_AFTER_REALTIME_EVENT) { - executeRealTime(); + executeMatches(AfterTimePred()); + } else if (event->getType() == OPENMSX_AFTER_TIMED_EVENT) { + executeMatches(AfterEmuTimePred()); } else { executeMatches(AfterInputEventPred(event)); for (auto& c : afterCmds) { @@ -542,8 +554,9 @@ void AfterTimedCmd::executeUntil(EmuTime::param /*time*/, int /*userData*/) { - shared_ptr<AfterCmd> self = removeSelf(); - execute(); + time = 0.0; // execute on next event + afterCommand.eventDistributor.distributeEvent( + std::make_shared<SimpleEvent>(OPENMSX_AFTER_TIMED_EVENT)); } void AfterTimedCmd::schedulerDeleted() @@ -620,10 +633,9 @@ // class AfterRealTimeCmd AfterRealTimeCmd::AfterRealTimeCmd( - AfterCommand& afterCommand, EventDistributor& eventDistributor_, + AfterCommand& afterCommand, const TclObject& command, double time) : AfterCmd(afterCommand, command) - , eventDistributor(eventDistributor_) , expired(false) { schedule(unsigned(time * 1000000)); // micro seconds @@ -644,7 +656,7 @@ // this runs in a different thread, so we can't directly execute the // command here expired = true; - eventDistributor.distributeEvent( + afterCommand.eventDistributor.distributeEvent( std::make_shared<SimpleEvent>(OPENMSX_AFTER_REALTIME_EVENT)); return false; // don't repeat alarm } Modified: openmsx/trunk/src/events/AfterCommand.hh =================================================================== --- openmsx/trunk/src/events/AfterCommand.hh 2013-03-09 12:43:11 UTC (rev 13188) +++ openmsx/trunk/src/events/AfterCommand.hh 2013-03-09 12:43:32 UTC (rev 13189) @@ -47,7 +47,6 @@ void afterIdle (const std::vector<TclObject>& tokens, TclObject& result); void afterInfo (const std::vector<TclObject>& tokens, TclObject& result); void afterCancel (const std::vector<TclObject>& tokens, TclObject& result); - void executeRealTime(); // EventListener virtual int signalEvent(const std::shared_ptr<const Event>& event); @@ -58,6 +57,8 @@ EventDistributor& eventDistributor; friend class AfterCmd; + friend class AfterTimedCmd; + friend class AfterRealTimeCmd; }; } // namespace openmsx Modified: openmsx/trunk/src/events/Event.hh =================================================================== --- openmsx/trunk/src/events/Event.hh 2013-03-09 12:43:11 UTC (rev 13188) +++ openmsx/trunk/src/events/Event.hh 2013-03-09 12:43:32 UTC (rev 13189) @@ -57,6 +57,9 @@ /** Command received on CliComm connection */ OPENMSX_CLICOMMAND_EVENT, + /** Send when an after-emutime command should be executed. */ + OPENMSX_AFTER_TIMED_EVENT, + /** This event is periodically send (50 times per second atm). * Used to implement polling (e.g SDL input events). */ OPENMSX_POLL_EVENT, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |