diff --git a/src/unix/uiactionx11.cpp b/src/unix/uiactionx11.cpp index fcfd677e1e..efa2d3fc18 100644 --- a/src/unix/uiactionx11.cpp +++ b/src/unix/uiactionx11.cpp @@ -16,6 +16,7 @@ #include "wx/uiaction.h" #include "wx/event.h" #include "wx/evtloop.h" +#include "wx/time.h" #include "wx/private/uiaction.h" @@ -55,17 +56,21 @@ namespace class wxXSync { public: + // This constructor is used before simulating mouse move events. wxXSync(wxX11Display& display) : m_display(display), m_isMotion(true) { + WaitIfNecessary(); } - wxXSync(wxX11Display& display, bool depressed) + // This constructor is used before simulating mouse button or key press or + // release events. Currently we handle presses and releases in the same + // way, so we don't use the "depressed" parameter, but it conveniently + // allows us to distinguish this ctor from the one above, so still keep it. + wxXSync(wxX11Display& display, bool WXUNUSED(depressed)) : m_display(display), m_isMotion(false) { - depressed ? ++ms_numDepressed : --ms_numDepressed; - - wxASSERT_MSG( ms_numDepressed >= 0, "Invalid call to wxXSync() ctor" ); + WaitIfNecessary(); } ~wxXSync() @@ -74,37 +79,45 @@ public: if ( m_isMotion ) { + // We need to yield here to let things update in response to + // the move, existing tests in wx own test suite rely on this + // (i.e. start failing if this wxYield() is removed) and doing + // this doesn't seem to result in any harm. wxYield(); } else // it's button or key event { - if ( ms_numDepressed > 0 ) - { - // Do nothing if a key / button is still depressed. - return; - } - - wxYield(); - wxMilliSleep(Default_Delay); + // Don't do anything here, in particular do not call wxYield() + // as dispatching events from inside e.g. KeyDown() call would + // be unexpected -- testing code using wxUIActionSimulator + // expects such events to be generated by a call to wxYield() + // after simulating them and this is how wxMSW works. } + + ms_lastEvent = wxGetLocalTimeMillis(); } private: + void WaitIfNecessary() + { + // Simulating events too fast results in just losing them somehow, so + // ensure that there is some minimal delay between subsequent events. + static int MIN_DELAY_BETWEEN_EVENTS = 20; + if ( wxGetLocalTimeMillis() < ms_lastEvent + MIN_DELAY_BETWEEN_EVENTS ) + wxMilliSleep(MIN_DELAY_BETWEEN_EVENTS); + } + wxX11Display& m_display; const bool m_isMotion; // false if it's button or key event. - enum - { - Default_Delay = 20 // amount of ms to sleep after key/button release. - }; - - static int ms_numDepressed; + // Time of the last simulated event. + static wxMilliClock_t ms_lastEvent; wxDECLARE_NO_COPY_CLASS(wxXSync); }; -/*static*/ -int wxXSync::ms_numDepressed = 0; +/* static */ +wxMilliClock_t wxXSync::ms_lastEvent = 0; // Base class for both available X11 implementations. class wxUIActionSimulatorX11Impl : public wxUIActionSimulatorImpl