]> git.saurik.com Git - wxWidgets.git/blame - tests/events/propagation.cpp
Make AsyncExecLoopExitEnum enum in the wxExecute() test public.
[wxWidgets.git] / tests / events / propagation.cpp
CommitLineData
1649d288
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: tests/events/propagation.cpp
3// Purpose: Test events propagation
4// Author: Vadim Zeitlin
5// Created: 2009-01-16
6// RCS-ID: $Id$
7// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
8///////////////////////////////////////////////////////////////////////////////
9
10// ----------------------------------------------------------------------------
11// headers
12// ----------------------------------------------------------------------------
13
14#include "testprec.h"
15
16#ifdef __BORLANDC__
17 #pragma hdrstop
18#endif
19
20#ifndef WX_PRECOMP
c21dcf80
VZ
21 #include "wx/app.h"
22 #include "wx/event.h"
ce45133e 23 #include "wx/scrolwin.h"
c21dcf80 24 #include "wx/window.h"
1649d288
VZ
25#endif // WX_PRECOMP
26
a7c0de8a 27#include "wx/docmdi.h"
3bad8c39
VZ
28#include "wx/frame.h"
29#include "wx/menu.h"
bbde2164 30#include "wx/scopedptr.h"
1649d288 31#include "wx/scopeguard.h"
dbd5b2ce 32#include "wx/uiaction.h"
1649d288 33
23366691
VZ
34// FIXME: Currently under OS X testing paint event doesn't work because neither
35// calling Refresh()+Update() nor even sending wxPaintEvent directly to
36// the window doesn't result in calls to its event handlers, so disable
37// some tests there. But this should be fixed and the tests reenabled
38// because wxPaintEvent propagation in wxScrolledWindow is a perfect
39// example of fragile code that could be broken under OS X.
40#ifndef __WXOSX__
41 #define CAN_TEST_PAINT_EVENTS
42#endif
43
1649d288
VZ
44namespace
45{
46
47// this string will record the execution of all handlers
48wxString g_str;
49
50// a custom event
51wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
52
ce45133e
VZ
53// a custom event handler tracing the propagation of the events of the
54// specified types
55template <class Event>
56class TestEvtHandlerBase : public wxEvtHandler
1649d288
VZ
57{
58public:
ce45133e
VZ
59 TestEvtHandlerBase(wxEventType evtType, char tag)
60 : m_evtType(evtType),
61 m_tag(tag)
1649d288 62 {
ce45133e
VZ
63 Connect(evtType,
64 static_cast<wxEventFunction>(&TestEvtHandlerBase::OnTest));
1649d288
VZ
65 }
66
67 // override ProcessEvent() to confirm that it is called for all event
68 // handlers in the chain
69 virtual bool ProcessEvent(wxEvent& event)
70 {
ce45133e 71 if ( event.GetEventType() == m_evtType )
1649d288
VZ
72 g_str += 'o'; // "o" == "overridden"
73
74 return wxEvtHandler::ProcessEvent(event);
75 }
76
77private:
ce45133e 78 void OnTest(wxEvent& event)
1649d288
VZ
79 {
80 g_str += m_tag;
81
82 event.Skip();
83 }
84
ce45133e 85 const wxEventType m_evtType;
1649d288
VZ
86 const char m_tag;
87
ce45133e
VZ
88 wxDECLARE_NO_COPY_TEMPLATE_CLASS(TestEvtHandlerBase, Event);
89};
90
91struct TestEvtHandler : TestEvtHandlerBase<wxCommandEvent>
92{
93 TestEvtHandler(char tag)
94 : TestEvtHandlerBase<wxCommandEvent>(TEST_EVT, tag)
95 {
96 }
97};
98
3bad8c39
VZ
99struct TestMenuEvtHandler : TestEvtHandlerBase<wxCommandEvent>
100{
101 TestMenuEvtHandler(char tag)
102 : TestEvtHandlerBase<wxCommandEvent>(wxEVT_MENU, tag)
103 {
104 }
105};
106
ce45133e
VZ
107struct TestPaintEvtHandler : TestEvtHandlerBase<wxPaintEvent>
108{
109 TestPaintEvtHandler(char tag)
110 : TestEvtHandlerBase<wxPaintEvent>(wxEVT_PAINT, tag)
111 {
112 }
1649d288
VZ
113};
114
a7c0de8a
VZ
115// Another custom event handler, suitable for use with Connect().
116struct TestEvtSink : wxEvtHandler
117{
118 TestEvtSink(char tag)
119 : m_tag(tag)
120 {
121 }
122
123 void Handle(wxEvent& event)
124 {
125 g_str += m_tag;
126
127 event.Skip();
128 }
129
130 const char m_tag;
131
132 wxDECLARE_NO_COPY_CLASS(TestEvtSink);
133};
134
1649d288
VZ
135// a window handling the test event
136class TestWindow : public wxWindow
137{
138public:
139 TestWindow(wxWindow *parent, char tag)
140 : wxWindow(parent, wxID_ANY),
141 m_tag(tag)
142 {
143 Connect(TEST_EVT, wxCommandEventHandler(TestWindow::OnTest));
144 }
145
146private:
147 void OnTest(wxCommandEvent& event)
148 {
149 g_str += m_tag;
150
151 event.Skip();
152 }
153
154 const char m_tag;
155
156 DECLARE_NO_COPY_CLASS(TestWindow)
157};
158
ce45133e
VZ
159// a scroll window handling paint event: we want to have a special test case
160// for this because the event propagation is complicated even further than
161// usual here by the presence of wxScrollHelperEvtHandler in the event handlers
162// chain and the fact that OnDraw() virtual method must be called if EVT_PAINT
163// is not handled
164class TestScrollWindow : public wxScrolledWindow
165{
166public:
167 TestScrollWindow(wxWindow *parent)
168 : wxScrolledWindow(parent, wxID_ANY)
169 {
170 Connect(wxEVT_PAINT, wxPaintEventHandler(TestScrollWindow::OnPaint));
171 }
172
23366691
VZ
173 void GeneratePaintEvent()
174 {
175#ifdef __WXGTK__
176 // We need to map the window, otherwise we're not going to get any
177 // paint events for it.
178 wxYield();
179
180 // Ignore events generated during the initial mapping.
181 g_str.clear();
182#endif // __WXGTK__
183
184 Refresh();
185 Update();
186 }
187
ce45133e
VZ
188 virtual void OnDraw(wxDC& WXUNUSED(dc))
189 {
190 g_str += 'D'; // draw
191 }
192
193private:
194 void OnPaint(wxPaintEvent& event)
195 {
196 g_str += 'P'; // paint
197 event.Skip();
198 }
199
200 wxDECLARE_NO_COPY_CLASS(TestScrollWindow);
201};
202
1649d288
VZ
203int DoFilterEvent(wxEvent& event)
204{
3bad8c39
VZ
205 if ( event.GetEventType() == TEST_EVT ||
206 event.GetEventType() == wxEVT_MENU )
1649d288
VZ
207 g_str += 'a';
208
209 return -1;
210}
211
212bool DoProcessEvent(wxEvent& event)
213{
3bad8c39
VZ
214 if ( event.GetEventType() == TEST_EVT ||
215 event.GetEventType() == wxEVT_MENU )
1649d288
VZ
216 g_str += 'A';
217
218 return false;
219}
220
221} // anonymous namespace
222
223// --------------------------------------------------------------------------
224// test class
225// --------------------------------------------------------------------------
226
227class EventPropagationTestCase : public CppUnit::TestCase
228{
229public:
230 EventPropagationTestCase() {}
231
232 virtual void setUp();
233 virtual void tearDown();
234
235private:
236 CPPUNIT_TEST_SUITE( EventPropagationTestCase );
237 CPPUNIT_TEST( OneHandler );
238 CPPUNIT_TEST( TwoHandlers );
239 CPPUNIT_TEST( WindowWithoutHandler );
240 CPPUNIT_TEST( WindowWithHandler );
bbdee10d 241 CPPUNIT_TEST( ForwardEvent );
ce45133e
VZ
242 CPPUNIT_TEST( ScrollWindowWithoutHandler );
243 CPPUNIT_TEST( ScrollWindowWithHandler );
3bad8c39 244 CPPUNIT_TEST( MenuEvent );
a7c0de8a 245 CPPUNIT_TEST( DocView );
dbd5b2ce 246 WXUISIM_TEST( ContextMenuEvent );
1649d288
VZ
247 CPPUNIT_TEST_SUITE_END();
248
249 void OneHandler();
250 void TwoHandlers();
251 void WindowWithoutHandler();
252 void WindowWithHandler();
bbdee10d 253 void ForwardEvent();
ce45133e
VZ
254 void ScrollWindowWithoutHandler();
255 void ScrollWindowWithHandler();
3bad8c39 256 void MenuEvent();
a7c0de8a 257 void DocView();
dbd5b2ce 258 void ContextMenuEvent();
1649d288
VZ
259
260 DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
261};
262
263// register in the unnamed registry so that these tests are run by default
264CPPUNIT_TEST_SUITE_REGISTRATION( EventPropagationTestCase );
265
e3778b4d 266// also include in its own registry so that these tests can be run alone
1649d288
VZ
267CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EventPropagationTestCase, "EventPropagationTestCase" );
268
269void EventPropagationTestCase::setUp()
270{
271 SetFilterEventFunc(DoFilterEvent);
272 SetProcessEventFunc(DoProcessEvent);
273
274 g_str.clear();
275}
276
277void EventPropagationTestCase::tearDown()
278{
279 SetFilterEventFunc(NULL);
280 SetProcessEventFunc(NULL);
281}
282
283void EventPropagationTestCase::OneHandler()
284{
285 wxCommandEvent event(TEST_EVT);
286 TestEvtHandler h1('1');
287 h1.ProcessEvent(event);
288 CPPUNIT_ASSERT_EQUAL( "oa1A", g_str );
289}
290
291void EventPropagationTestCase::TwoHandlers()
292{
293 wxCommandEvent event(TEST_EVT);
294 TestEvtHandler h1('1');
295 TestEvtHandler h2('2');
296 h1.SetNextHandler(&h2);
297 h2.SetPreviousHandler(&h1);
298 h1.ProcessEvent(event);
299 CPPUNIT_ASSERT_EQUAL( "oa1o2A", g_str );
300}
301
302void EventPropagationTestCase::WindowWithoutHandler()
303{
304 wxCommandEvent event(TEST_EVT);
305 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
306 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
307
308 TestWindow * const child = new TestWindow(parent, 'c');
309
004867db 310 child->GetEventHandler()->ProcessEvent(event);
1649d288
VZ
311 CPPUNIT_ASSERT_EQUAL( "acpA", g_str );
312}
313
314void EventPropagationTestCase::WindowWithHandler()
315{
316 wxCommandEvent event(TEST_EVT);
317 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
318 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
319
320 TestWindow * const child = new TestWindow(parent, 'c');
321
322 TestEvtHandler h1('1');
323 child->PushEventHandler(&h1);
9ebfc963 324 wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
1649d288
VZ
325 TestEvtHandler h2('2');
326 child->PushEventHandler(&h2);
9ebfc963 327 wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
1649d288
VZ
328
329 child->HandleWindowEvent(event);
330 CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
331}
332
bbdee10d
VZ
333void EventPropagationTestCase::ForwardEvent()
334{
335 // The idea of this test is to check that the events explicitly forwarded
336 // to another event handler still get pre/post-processed as usual as this
337 // used to be broken by the fixes trying to avoid duplicate processing.
338 TestWindow * const win = new TestWindow(wxTheApp->GetTopWindow(), 'w');
339 wxON_BLOCK_EXIT_OBJ0( *win, wxWindow::Destroy );
340
341 TestEvtHandler h1('1');
342 win->PushEventHandler(&h1);
343 wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
344
345 class ForwardEvtHandler : public wxEvtHandler
346 {
347 public:
348 ForwardEvtHandler(wxEvtHandler& h) : m_h(&h) { }
349
350 virtual bool ProcessEvent(wxEvent& event)
351 {
352 g_str += 'f';
353
354 return m_h->ProcessEvent(event);
355 }
356
357 private:
358 wxEvtHandler *m_h;
359 } f(h1);
360
361 // First send the event directly to f.
362 wxCommandEvent event1(TEST_EVT);
363 f.ProcessEvent(event1);
364 CPPUNIT_ASSERT_EQUAL( "foa1wA", g_str );
365 g_str.clear();
366
367 // And then also test sending it to f indirectly.
368 wxCommandEvent event2(TEST_EVT);
369 TestEvtHandler h2('2');
370 h2.SetNextHandler(&f);
371 h2.ProcessEvent(event2);
372 CPPUNIT_ASSERT_EQUAL( "oa2fo1wAA", g_str );
373}
374
ce45133e
VZ
375void EventPropagationTestCase::ScrollWindowWithoutHandler()
376{
52212bcb
VZ
377 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
378 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
379
380 TestScrollWindow * const win = new TestScrollWindow(parent);
ce45133e 381
23366691
VZ
382#ifdef CAN_TEST_PAINT_EVENTS
383 win->GeneratePaintEvent();
ce45133e 384 CPPUNIT_ASSERT_EQUAL( "PD", g_str );
f009da6e 385#endif
23366691 386
52212bcb
VZ
387 g_str.clear();
388 wxCommandEvent eventCmd(TEST_EVT);
389 win->HandleWindowEvent(eventCmd);
390 CPPUNIT_ASSERT_EQUAL( "apA", g_str );
ce45133e
VZ
391}
392
393void EventPropagationTestCase::ScrollWindowWithHandler()
394{
52212bcb
VZ
395 TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
396 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
397
398 TestScrollWindow * const win = new TestScrollWindow(parent);
ce45133e 399
23366691 400#ifdef CAN_TEST_PAINT_EVENTS
ce45133e
VZ
401 TestPaintEvtHandler h('h');
402 win->PushEventHandler(&h);
403 wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
404
23366691 405 win->GeneratePaintEvent();
ce45133e 406 CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
15536294 407#endif
52212bcb
VZ
408
409 g_str.clear();
410 wxCommandEvent eventCmd(TEST_EVT);
411 win->HandleWindowEvent(eventCmd);
412 CPPUNIT_ASSERT_EQUAL( "apA", g_str );
ce45133e
VZ
413}
414
bbde2164
VZ
415// Create a menu bar with a single menu containing wxID_APPLY menu item and
416// attach it to the specified frame.
417wxMenu* CreateTestMenu(wxFrame* frame)
418{
419 wxMenu* const menu = new wxMenu;
420 menu->Append(wxID_APPLY);
421 wxMenuBar* const mb = new wxMenuBar;
422 mb->Append(menu, "&Menu");
423 frame->SetMenuBar(mb);
424
425 return menu;
426}
427
3bad8c39
VZ
428// Helper for checking that the menu event processing resulted in the expected
429// output from the handlers.
9fe94219
VZ
430//
431// Notice that this is supposed to be used with ASSERT_MENU_EVENT_RESULT()
432// macro to make the file name and line number of the caller appear in the
433// failure messages.
434void
435CheckMenuEvent(wxMenu* menu, const char* result, CppUnit::SourceLine sourceLine)
3bad8c39
VZ
436{
437 g_str.clear();
438
439 // Trigger the menu event: this is more reliable than using
440 // wxUIActionSimulator and currently works in all ports as they all call
441 // wxMenuBase::SendEvent() from their respective menu event handlers.
bbde2164 442 menu->SendEvent(wxID_APPLY);
3bad8c39 443
9fe94219 444 CPPUNIT_NS::assertEquals( result, g_str, sourceLine, "" );
3bad8c39
VZ
445}
446
9fe94219
VZ
447#define ASSERT_MENU_EVENT_RESULT(menu, result) \
448 CheckMenuEvent((menu), (result), CPPUNIT_SOURCELINE())
449
3bad8c39
VZ
450void EventPropagationTestCase::MenuEvent()
451{
3bad8c39 452 wxFrame* const frame = static_cast<wxFrame*>(wxTheApp->GetTopWindow());
bbde2164
VZ
453
454 // Create a minimal menu bar.
455 wxMenu* const menu = CreateTestMenu(frame);
456 wxMenuBar* const mb = menu->GetMenuBar();
457 wxScopedPtr<wxMenuBar> ensureMenuBarDestruction(mb);
3bad8c39
VZ
458 wxON_BLOCK_EXIT_OBJ1( *frame, wxFrame::SetMenuBar, (wxMenuBar*)NULL );
459
460 // Check that wxApp gets the event exactly once.
9fe94219 461 ASSERT_MENU_EVENT_RESULT( menu, "aA" );
3bad8c39
VZ
462
463
464 // Check that the menu event handler is called.
465 TestMenuEvtHandler hm('m'); // 'm' for "menu"
466 menu->SetNextHandler(&hm);
467 wxON_BLOCK_EXIT_OBJ1( *menu,
468 wxEvtHandler::SetNextHandler, (wxEvtHandler*)NULL );
9fe94219 469 ASSERT_MENU_EVENT_RESULT( menu, "aomA" );
3bad8c39
VZ
470
471
4ed3f4ab
VZ
472 // Test that the event handler associated with the menu bar gets the event.
473 TestMenuEvtHandler hb('b'); // 'b' for "menu Bar"
474 mb->PushEventHandler(&hb);
475 wxON_BLOCK_EXIT_OBJ1( *mb, wxWindow::PopEventHandler, false );
476
9fe94219 477 ASSERT_MENU_EVENT_RESULT( menu, "aomobA" );
4ed3f4ab
VZ
478
479
3bad8c39
VZ
480 // Also test that the window to which the menu belongs gets the event.
481 TestMenuEvtHandler hw('w'); // 'w' for "Window"
482 frame->PushEventHandler(&hw);
483 wxON_BLOCK_EXIT_OBJ1( *frame, wxWindow::PopEventHandler, false );
484
9fe94219 485 ASSERT_MENU_EVENT_RESULT( menu, "aomobowA" );
3bad8c39 486}
a7c0de8a
VZ
487
488// Minimal viable implementations of wxDocument and wxView.
489class EventTestDocument : public wxDocument
490{
491public:
492 EventTestDocument() { }
493
494 wxDECLARE_DYNAMIC_CLASS(EventTestDocument);
495};
496
497class EventTestView : public wxView
498{
499public:
500 EventTestView() { }
501
502 virtual void OnDraw(wxDC*) { }
503
504 wxDECLARE_DYNAMIC_CLASS(EventTestView);
505};
506
507wxIMPLEMENT_DYNAMIC_CLASS(EventTestDocument, wxDocument);
508wxIMPLEMENT_DYNAMIC_CLASS(EventTestView, wxView);
509
510void EventPropagationTestCase::DocView()
511{
512 // Set up the parent frame and its menu bar.
513 wxDocManager docManager;
514
515 wxScopedPtr<wxDocMDIParentFrame>
516 parent(new wxDocMDIParentFrame(&docManager, NULL, wxID_ANY, "Parent"));
517
518 wxMenu* const menu = CreateTestMenu(parent.get());
519
520
521 // Set up the event handlers.
522 TestEvtSink sinkDM('m');
523 docManager.Connect(wxEVT_MENU,
524 wxEventHandler(TestEvtSink::Handle), NULL, &sinkDM);
525
526 TestEvtSink sinkParent('p');
527 parent->Connect(wxEVT_MENU,
528 wxEventHandler(TestEvtSink::Handle), NULL, &sinkParent);
529
530
531 // Check that wxDocManager and wxFrame get the event in order.
532 ASSERT_MENU_EVENT_RESULT( menu, "ampA" );
533
534
535 // Now check what happens if we have an active document.
536 wxDocTemplate docTemplate(&docManager, "Test", "", "", "",
537 "Test Document", "Test View",
538 wxCLASSINFO(EventTestDocument),
539 wxCLASSINFO(EventTestView));
540 wxDocument* const doc = docTemplate.CreateDocument("");
541 wxView* const view = doc->GetFirstView();
542
543 wxScopedPtr<wxFrame>
544 child(new wxDocMDIChildFrame(doc, view, parent.get(), wxID_ANY, "Child"));
545
546 wxMenu* const menuChild = CreateTestMenu(child.get());
547
548#ifdef __WXGTK__
549 // There are a lot of hacks related to child frame menu bar handling in
550 // wxGTK and, in particular, the code in src/gtk/mdi.cpp relies on getting
551 // idle events to really put everything in place. Moreover, as wxGTK uses
552 // GtkNotebook as its MDI pages container, the frame must be shown for all
553 // this to work as gtk_notebook_set_current_page() doesn't do anything if
554 // called for a hidden window (this incredible fact cost me quite some time
555 // to find empirically -- only to notice its confirmation in GTK+
556 // documentation immediately afterwards). So just do whatever it takes to
557 // make things work "as usual".
558 child->Show();
559 parent->Show();
560 wxYield();
561#endif // __WXGTK__
562
563 TestEvtSink sinkDoc('d');
564 doc->Connect(wxEVT_MENU,
565 wxEventHandler(TestEvtSink::Handle), NULL, &sinkDoc);
566
567 TestEvtSink sinkView('v');
568 view->Connect(wxEVT_MENU,
569 wxEventHandler(TestEvtSink::Handle), NULL, &sinkView);
570
571 TestEvtSink sinkChild('c');
572 child->Connect(wxEVT_MENU,
573 wxEventHandler(TestEvtSink::Handle), NULL, &sinkChild);
574
575 // Check that wxDocument, wxView, wxDocManager, child frame and the parent
576 // get the event in order.
577 ASSERT_MENU_EVENT_RESULT( menuChild, "advmcpA" );
578}
dbd5b2ce
VZ
579
580#if wxUSE_UIACTIONSIMULATOR
581
582class ContextMenuTestWindow : public wxWindow
583{
584public:
585 ContextMenuTestWindow(wxWindow *parent, char tag)
586 : wxWindow(parent, wxID_ANY),
587 m_tag(tag)
588 {
589 Connect(wxEVT_CONTEXT_MENU,
590 wxContextMenuEventHandler(ContextMenuTestWindow::OnMenu));
591 }
592
593private:
594 void OnMenu(wxContextMenuEvent& event)
595 {
596 g_str += m_tag;
597
598 event.Skip();
599 }
600
601 const char m_tag;
602
603 wxDECLARE_NO_COPY_CLASS(ContextMenuTestWindow);
604};
605
606void EventPropagationTestCase::ContextMenuEvent()
607{
608 ContextMenuTestWindow * const
609 parent = new ContextMenuTestWindow(wxTheApp->GetTopWindow(), 'p');
610 wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
611
612 ContextMenuTestWindow * const
613 child = new ContextMenuTestWindow(parent, 'c');
614 parent->SetSize(100, 100);
615 child->SetSize(0, 0, 50, 50);
616 child->SetFocus();
617
618 wxUIActionSimulator sim;
619 const wxPoint origin = parent->ClientToScreen(wxPoint(0, 0));
620
621 // Right clicking in the child should generate an event for it and the
622 // parent.
623 g_str.clear();
624 sim.MouseMove(origin + wxPoint(10, 10));
625 sim.MouseClick(wxMOUSE_BTN_RIGHT);
626
627 // At least with MSW, for WM_CONTEXTMENU to be synthesized by the system
628 // from the right mouse click event, we must dispatch the mouse messages.
629 wxYield();
630
631 CPPUNIT_ASSERT_EQUAL( "cp", g_str );
632
633 // Right clicking outside the child should generate the event just in the
634 // parent.
635 g_str.clear();
636 sim.MouseMove(origin + wxPoint(60, 60));
637 sim.MouseClick(wxMOUSE_BTN_RIGHT);
638 wxYield();
639 CPPUNIT_ASSERT_EQUAL( "p", g_str );
640}
641
642#endif // wxUSE_UIACTIONSIMULATOR