OScopeCtrl.cpp: use Refresh() instead of ProcessEvent() to refresh the UI, fix #146.
In OScopeCtrl.cpp, a timer, timerRedraw is used to refresh the GUI. The
refresh is implemented by creating a wxPaintEvent and calling ProcessEvent()
in OnTimer().
However, it is incorrect, as wxBufferedPaintDC, being a subclass of wxPaintDC,
is only allowed to be used within a EVT_PAINT() handler, OnPaint(). It's illegal
to create an artifical wxPaintEvent and process it in an EVT_TIMER, or other
handlers. Otherwise, it causes an undefined behavior, which is not guaranteed
to work correctly.
In the history of aMule, it already causes a malfunction of GUI on Mac OS X, as
a result, the timer is disabled in commit
10b0621ef [1] for Mac. Also, on some
systems, it triggers an instant crash of the entire application due to an assertion
failure in wxWidget [2],
> assert "cr" failed in wxPaintDCImpl(): using wxPaintDC without being
> in a native paint event
However, on most systems, the undefined behavior happened to work by chance,
and since most systems disabled the assertions in wxWidget by default, the root
of the problem is never identified.
According to the upstream developers of wxWidgets, posting a wxPaintEvent is
"definitely" wrong, and the proper way to refresh the GUI should be using the
Refresh() function just for this purpose. [3]
This commit replaced the old code, and uses Refresh() to refresh the UI to solve
the above problems.
The function, Refresh(), adds a pending wxPaintEvent waiting to be executed for
a redraw in the event loop. There is also a function, Update(), which triggers
an immediate redraw, but this is not necessary and should only be used in special
cases [4], so only Refresh() is used.
A test run on my own system shows that the assertion failure is corrected, and
the charts for the network statistics is redrawn properly. It should also fix
the previous problem on Mac OS X, and we should revert commit
10b0621ef. But
someone needs to test it first.
[0] https://docs.wxwidgets.org/trunk/classwx_paint_d_c.html
> To draw on a window from outside your EVT_PAINT() handler,
> construct a wxClientDC object.
[1] https://github.com/amule-project/amule/commit/
10b0621ef
> It appears the timerRedraw logic screws up Mac, disable it there.
[2] http://forum.amule.org/index.php?topic=21383.15
[3] https://groups.google.com/forum/#!msg/wx-users/_6GCTegdpuI/0eqeJ80ACwAJ
[4] https://forums.wxwidgets.org/viewtopic.php?t=10114
Signed-off-by: Tom Li <tomli@tomli.me>