| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 | 
							- ///////////////////////////////////////////////////////////////////////////////
 
- // Name:        tests/events/propagation.cpp
 
- // Purpose:     Test events propagation
 
- // Author:      Vadim Zeitlin
 
- // Created:     2009-01-16
 
- // Copyright:   (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
 
- ///////////////////////////////////////////////////////////////////////////////
 
- // ----------------------------------------------------------------------------
 
- // headers
 
- // ----------------------------------------------------------------------------
 
- #include "testprec.h"
 
- #ifdef __BORLANDC__
 
-     #pragma hdrstop
 
- #endif
 
- #ifndef WX_PRECOMP
 
-     #include "wx/app.h"
 
-     #include "wx/event.h"
 
-     #include "wx/scrolwin.h"
 
-     #include "wx/window.h"
 
- #endif // WX_PRECOMP
 
- #include "wx/docmdi.h"
 
- #include "wx/frame.h"
 
- #include "wx/menu.h"
 
- #include "wx/scopedptr.h"
 
- #include "wx/scopeguard.h"
 
- #include "wx/toolbar.h"
 
- #include "wx/uiaction.h"
 
- // FIXME: Currently under OS X testing paint event doesn't work because neither
 
- //        calling Refresh()+Update() nor even sending wxPaintEvent directly to
 
- //        the window doesn't result in calls to its event handlers, so disable
 
- //        some tests there. But this should be fixed and the tests reenabled
 
- //        because wxPaintEvent propagation in wxScrolledWindow is a perfect
 
- //        example of fragile code that could be broken under OS X.
 
- #ifndef __WXOSX__
 
-     #define CAN_TEST_PAINT_EVENTS
 
- #endif
 
- namespace
 
- {
 
- // this string will record the execution of all handlers
 
- wxString g_str;
 
- // a custom event
 
- wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
 
- // a custom event handler tracing the propagation of the events of the
 
- // specified types
 
- template <class Event>
 
- class TestEvtHandlerBase : public wxEvtHandler
 
- {
 
- public:
 
-     TestEvtHandlerBase(wxEventType evtType, char tag)
 
-         : m_evtType(evtType),
 
-           m_tag(tag)
 
-     {
 
-         Connect(evtType,
 
-                 static_cast<wxEventFunction>(&TestEvtHandlerBase::OnTest));
 
-     }
 
-     // override ProcessEvent() to confirm that it is called for all event
 
-     // handlers in the chain
 
-     virtual bool ProcessEvent(wxEvent& event)
 
-     {
 
-         if ( event.GetEventType() == m_evtType )
 
-             g_str += 'o'; // "o" == "overridden"
 
-         return wxEvtHandler::ProcessEvent(event);
 
-     }
 
- private:
 
-     void OnTest(wxEvent& event)
 
-     {
 
-         g_str += m_tag;
 
-         event.Skip();
 
-     }
 
-     const wxEventType m_evtType;
 
-     const char m_tag;
 
-     wxDECLARE_NO_COPY_TEMPLATE_CLASS(TestEvtHandlerBase, Event);
 
- };
 
- struct TestEvtHandler : TestEvtHandlerBase<wxCommandEvent>
 
- {
 
-     TestEvtHandler(char tag)
 
-         : TestEvtHandlerBase<wxCommandEvent>(TEST_EVT, tag)
 
-     {
 
-     }
 
- };
 
- struct TestMenuEvtHandler : TestEvtHandlerBase<wxCommandEvent>
 
- {
 
-     TestMenuEvtHandler(char tag)
 
-         : TestEvtHandlerBase<wxCommandEvent>(wxEVT_MENU, tag)
 
-     {
 
-     }
 
- };
 
- struct TestPaintEvtHandler : TestEvtHandlerBase<wxPaintEvent>
 
- {
 
-     TestPaintEvtHandler(char tag)
 
-         : TestEvtHandlerBase<wxPaintEvent>(wxEVT_PAINT, tag)
 
-     {
 
-     }
 
- };
 
- // Another custom event handler, suitable for use with Connect().
 
- struct TestEvtSink : wxEvtHandler
 
- {
 
-     TestEvtSink(char tag)
 
-         : m_tag(tag)
 
-     {
 
-     }
 
-     void Handle(wxEvent& event)
 
-     {
 
-         g_str += m_tag;
 
-         event.Skip();
 
-     }
 
-     const char m_tag;
 
-     wxDECLARE_NO_COPY_CLASS(TestEvtSink);
 
- };
 
- // a window handling the test event
 
- class TestWindow : public wxWindow
 
- {
 
- public:
 
-     TestWindow(wxWindow *parent, char tag)
 
-         : wxWindow(parent, wxID_ANY),
 
-           m_tag(tag)
 
-     {
 
-         Connect(TEST_EVT, wxCommandEventHandler(TestWindow::OnTest));
 
-     }
 
- private:
 
-     void OnTest(wxCommandEvent& event)
 
-     {
 
-         g_str += m_tag;
 
-         event.Skip();
 
-     }
 
-     const char m_tag;
 
-     DECLARE_NO_COPY_CLASS(TestWindow)
 
- };
 
- // a scroll window handling paint event: we want to have a special test case
 
- // for this because the event propagation is complicated even further than
 
- // usual here by the presence of wxScrollHelperEvtHandler in the event handlers
 
- // chain and the fact that OnDraw() virtual method must be called if EVT_PAINT
 
- // is not handled
 
- class TestScrollWindow : public wxScrolledWindow
 
- {
 
- public:
 
-     TestScrollWindow(wxWindow *parent)
 
-         : wxScrolledWindow(parent, wxID_ANY)
 
-     {
 
-         Connect(wxEVT_PAINT, wxPaintEventHandler(TestScrollWindow::OnPaint));
 
-     }
 
-     void GeneratePaintEvent()
 
-     {
 
- #ifdef __WXGTK__
 
-         // We need to map the window, otherwise we're not going to get any
 
-         // paint events for it.
 
-         wxYield();
 
-         // Ignore events generated during the initial mapping.
 
-         g_str.clear();
 
- #endif // __WXGTK__
 
-         Refresh();
 
-         Update();
 
-     }
 
-     virtual void OnDraw(wxDC& WXUNUSED(dc))
 
-     {
 
-         g_str += 'D';   // draw
 
-     }
 
- private:
 
-     void OnPaint(wxPaintEvent& event)
 
-     {
 
-         g_str += 'P';   // paint
 
-         event.Skip();
 
-     }
 
-     wxDECLARE_NO_COPY_CLASS(TestScrollWindow);
 
- };
 
- int DoFilterEvent(wxEvent& event)
 
- {
 
-     if ( event.GetEventType() == TEST_EVT ||
 
-             event.GetEventType() == wxEVT_MENU )
 
-         g_str += 'a';
 
-     return -1;
 
- }
 
- bool DoProcessEvent(wxEvent& event)
 
- {
 
-     if ( event.GetEventType() == TEST_EVT ||
 
-             event.GetEventType() == wxEVT_MENU )
 
-         g_str += 'A';
 
-     return false;
 
- }
 
- } // anonymous namespace
 
- // --------------------------------------------------------------------------
 
- // test class
 
- // --------------------------------------------------------------------------
 
- class EventPropagationTestCase : public CppUnit::TestCase
 
- {
 
- public:
 
-     EventPropagationTestCase() {}
 
-     virtual void setUp();
 
-     virtual void tearDown();
 
- private:
 
-     CPPUNIT_TEST_SUITE( EventPropagationTestCase );
 
-         CPPUNIT_TEST( OneHandler );
 
-         CPPUNIT_TEST( TwoHandlers );
 
-         CPPUNIT_TEST( WindowWithoutHandler );
 
-         CPPUNIT_TEST( WindowWithHandler );
 
-         CPPUNIT_TEST( ForwardEvent );
 
-         CPPUNIT_TEST( ScrollWindowWithoutHandler );
 
-         CPPUNIT_TEST( ScrollWindowWithHandler );
 
-         CPPUNIT_TEST( MenuEvent );
 
-         CPPUNIT_TEST( DocView );
 
-         WXUISIM_TEST( ContextMenuEvent );
 
-     CPPUNIT_TEST_SUITE_END();
 
-     void OneHandler();
 
-     void TwoHandlers();
 
-     void WindowWithoutHandler();
 
-     void WindowWithHandler();
 
-     void ForwardEvent();
 
-     void ScrollWindowWithoutHandler();
 
-     void ScrollWindowWithHandler();
 
-     void MenuEvent();
 
-     void DocView();
 
-     void ContextMenuEvent();
 
-     DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
 
- };
 
- // register in the unnamed registry so that these tests are run by default
 
- CPPUNIT_TEST_SUITE_REGISTRATION( EventPropagationTestCase );
 
- // also include in its own registry so that these tests can be run alone
 
- CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EventPropagationTestCase, "EventPropagationTestCase" );
 
- void EventPropagationTestCase::setUp()
 
- {
 
-     SetFilterEventFunc(DoFilterEvent);
 
-     SetProcessEventFunc(DoProcessEvent);
 
-     g_str.clear();
 
- }
 
- void EventPropagationTestCase::tearDown()
 
- {
 
-     SetFilterEventFunc(NULL);
 
-     SetProcessEventFunc(NULL);
 
- }
 
- void EventPropagationTestCase::OneHandler()
 
- {
 
-     wxCommandEvent event(TEST_EVT);
 
-     TestEvtHandler h1('1');
 
-     h1.ProcessEvent(event);
 
-     CPPUNIT_ASSERT_EQUAL( "oa1A", g_str );
 
- }
 
- void EventPropagationTestCase::TwoHandlers()
 
- {
 
-     wxCommandEvent event(TEST_EVT);
 
-     TestEvtHandler h1('1');
 
-     TestEvtHandler h2('2');
 
-     h1.SetNextHandler(&h2);
 
-     h2.SetPreviousHandler(&h1);
 
-     h1.ProcessEvent(event);
 
-     CPPUNIT_ASSERT_EQUAL( "oa1o2A", g_str );
 
- }
 
- void EventPropagationTestCase::WindowWithoutHandler()
 
- {
 
-     wxCommandEvent event(TEST_EVT);
 
-     TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
 
-     wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
 
-     TestWindow * const child = new TestWindow(parent, 'c');
 
-     child->GetEventHandler()->ProcessEvent(event);
 
-     CPPUNIT_ASSERT_EQUAL( "acpA", g_str );
 
- }
 
- void EventPropagationTestCase::WindowWithHandler()
 
- {
 
-     wxCommandEvent event(TEST_EVT);
 
-     TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
 
-     wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
 
-     TestWindow * const child = new TestWindow(parent, 'c');
 
-     TestEvtHandler h1('1');
 
-     child->PushEventHandler(&h1);
 
-     wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
 
-     TestEvtHandler h2('2');
 
-     child->PushEventHandler(&h2);
 
-     wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
 
-     child->HandleWindowEvent(event);
 
-     CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
 
- }
 
- void EventPropagationTestCase::ForwardEvent()
 
- {
 
-     // The idea of this test is to check that the events explicitly forwarded
 
-     // to another event handler still get pre/post-processed as usual as this
 
-     // used to be broken by the fixes trying to avoid duplicate processing.
 
-     TestWindow * const win = new TestWindow(wxTheApp->GetTopWindow(), 'w');
 
-     wxON_BLOCK_EXIT_OBJ0( *win, wxWindow::Destroy );
 
-     TestEvtHandler h1('1');
 
-     win->PushEventHandler(&h1);
 
-     wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
 
-     class ForwardEvtHandler : public wxEvtHandler
 
-     {
 
-     public:
 
-         ForwardEvtHandler(wxEvtHandler& h) : m_h(&h) { }
 
-         virtual bool ProcessEvent(wxEvent& event)
 
-         {
 
-             g_str += 'f';
 
-             return m_h->ProcessEvent(event);
 
-         }
 
-     private:
 
-         wxEvtHandler *m_h;
 
-     } f(h1);
 
-     // First send the event directly to f.
 
-     wxCommandEvent event1(TEST_EVT);
 
-     f.ProcessEvent(event1);
 
-     CPPUNIT_ASSERT_EQUAL( "foa1wA", g_str );
 
-     g_str.clear();
 
-     // And then also test sending it to f indirectly.
 
-     wxCommandEvent event2(TEST_EVT);
 
-     TestEvtHandler h2('2');
 
-     h2.SetNextHandler(&f);
 
-     h2.ProcessEvent(event2);
 
-     CPPUNIT_ASSERT_EQUAL( "oa2fo1wAA", g_str );
 
- }
 
- void EventPropagationTestCase::ScrollWindowWithoutHandler()
 
- {
 
-     TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
 
-     wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
 
-     TestScrollWindow * const win = new TestScrollWindow(parent);
 
- #ifdef CAN_TEST_PAINT_EVENTS
 
-     win->GeneratePaintEvent();
 
-     CPPUNIT_ASSERT_EQUAL( "PD", g_str );
 
- #endif
 
-     g_str.clear();
 
-     wxCommandEvent eventCmd(TEST_EVT);
 
-     win->HandleWindowEvent(eventCmd);
 
-     CPPUNIT_ASSERT_EQUAL( "apA", g_str );
 
- }
 
- void EventPropagationTestCase::ScrollWindowWithHandler()
 
- {
 
-     TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
 
-     wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
 
-     TestScrollWindow * const win = new TestScrollWindow(parent);
 
- #ifdef CAN_TEST_PAINT_EVENTS
 
-     TestPaintEvtHandler h('h');
 
-     win->PushEventHandler(&h);
 
-     wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
 
-     win->GeneratePaintEvent();
 
-     CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
 
- #endif
 
-     g_str.clear();
 
-     wxCommandEvent eventCmd(TEST_EVT);
 
-     win->HandleWindowEvent(eventCmd);
 
-     CPPUNIT_ASSERT_EQUAL( "apA", g_str );
 
- }
 
- // Create a menu bar with a single menu containing wxID_APPLY menu item and
 
- // attach it to the specified frame.
 
- wxMenu* CreateTestMenu(wxFrame* frame)
 
- {
 
-     wxMenu* const menu = new wxMenu;
 
-     menu->Append(wxID_APPLY);
 
-     wxMenuBar* const mb = new wxMenuBar;
 
-     mb->Append(menu, "&Menu");
 
-     frame->SetMenuBar(mb);
 
-     return menu;
 
- }
 
- // Helper for checking that the menu event processing resulted in the expected
 
- // output from the handlers.
 
- //
 
- // Notice that this is supposed to be used with ASSERT_MENU_EVENT_RESULT()
 
- // macro to make the file name and line number of the caller appear in the
 
- // failure messages.
 
- void
 
- CheckMenuEvent(wxMenu* menu, const char* result, CppUnit::SourceLine sourceLine)
 
- {
 
-     g_str.clear();
 
-     // Trigger the menu event: this is more reliable than using
 
-     // wxUIActionSimulator and currently works in all ports as they all call
 
-     // wxMenuBase::SendEvent() from their respective menu event handlers.
 
-     menu->SendEvent(wxID_APPLY);
 
-     CPPUNIT_NS::assertEquals( result, g_str, sourceLine, "" );
 
- }
 
- #define ASSERT_MENU_EVENT_RESULT(menu, result) \
 
-     CheckMenuEvent((menu), (result), CPPUNIT_SOURCELINE())
 
- void EventPropagationTestCase::MenuEvent()
 
- {
 
-     wxFrame* const frame = static_cast<wxFrame*>(wxTheApp->GetTopWindow());
 
-     // Create a minimal menu bar.
 
-     wxMenu* const menu = CreateTestMenu(frame);
 
-     wxMenuBar* const mb = menu->GetMenuBar();
 
-     wxScopedPtr<wxMenuBar> ensureMenuBarDestruction(mb);
 
-     wxON_BLOCK_EXIT_OBJ1( *frame, wxFrame::SetMenuBar, (wxMenuBar*)NULL );
 
-     // Check that wxApp gets the event exactly once.
 
-     ASSERT_MENU_EVENT_RESULT( menu, "aA" );
 
-     // Check that the menu event handler is called.
 
-     TestMenuEvtHandler hm('m'); // 'm' for "menu"
 
-     menu->SetNextHandler(&hm);
 
-     wxON_BLOCK_EXIT_OBJ1( *menu,
 
-                           wxEvtHandler::SetNextHandler, (wxEvtHandler*)NULL );
 
-     ASSERT_MENU_EVENT_RESULT( menu, "aomA" );
 
-     // Test that the event handler associated with the menu bar gets the event.
 
-     TestMenuEvtHandler hb('b'); // 'b' for "menu Bar"
 
-     mb->PushEventHandler(&hb);
 
-     wxON_BLOCK_EXIT_OBJ1( *mb, wxWindow::PopEventHandler, false );
 
-     ASSERT_MENU_EVENT_RESULT( menu, "aomobA" );
 
-     // Also test that the window to which the menu belongs gets the event.
 
-     TestMenuEvtHandler hw('w'); // 'w' for "Window"
 
-     frame->PushEventHandler(&hw);
 
-     wxON_BLOCK_EXIT_OBJ1( *frame, wxWindow::PopEventHandler, false );
 
-     ASSERT_MENU_EVENT_RESULT( menu, "aomobowA" );
 
- }
 
- // Minimal viable implementations of wxDocument and wxView.
 
- class EventTestDocument : public wxDocument
 
- {
 
- public:
 
-     EventTestDocument() { }
 
-     wxDECLARE_DYNAMIC_CLASS(EventTestDocument);
 
- };
 
- class EventTestView : public wxView
 
- {
 
- public:
 
-     EventTestView() { }
 
-     virtual void OnDraw(wxDC*) { }
 
-     wxDECLARE_DYNAMIC_CLASS(EventTestView);
 
- };
 
- wxIMPLEMENT_DYNAMIC_CLASS(EventTestDocument, wxDocument);
 
- wxIMPLEMENT_DYNAMIC_CLASS(EventTestView, wxView);
 
- void EventPropagationTestCase::DocView()
 
- {
 
-     // Set up the parent frame and its menu bar.
 
-     wxDocManager docManager;
 
-     wxScopedPtr<wxDocMDIParentFrame>
 
-         parent(new wxDocMDIParentFrame(&docManager, NULL, wxID_ANY, "Parent"));
 
-     wxMenu* const menu = CreateTestMenu(parent.get());
 
-     // Set up the event handlers.
 
-     TestEvtSink sinkDM('m');
 
-     docManager.Connect(wxEVT_MENU,
 
-                        wxEventHandler(TestEvtSink::Handle), NULL, &sinkDM);
 
-     TestEvtSink sinkParent('p');
 
-     parent->Connect(wxEVT_MENU,
 
-                     wxEventHandler(TestEvtSink::Handle), NULL, &sinkParent);
 
-     // Check that wxDocManager and wxFrame get the event in order.
 
-     ASSERT_MENU_EVENT_RESULT( menu, "ampA" );
 
-     // Now check what happens if we have an active document.
 
-     wxDocTemplate docTemplate(&docManager, "Test", "", "", "",
 
-                               "Test Document", "Test View",
 
-                               wxCLASSINFO(EventTestDocument),
 
-                               wxCLASSINFO(EventTestView));
 
-     wxDocument* const doc = docTemplate.CreateDocument("");
 
-     wxView* const view = doc->GetFirstView();
 
-     wxScopedPtr<wxMDIChildFrame>
 
-         child(new wxDocMDIChildFrame(doc, view, parent.get(), wxID_ANY, "Child"));
 
-     wxMenu* const menuChild = CreateTestMenu(child.get());
 
-     // Ensure that the child that we've just created is the active one.
 
-     child->Activate();
 
- #ifdef __WXGTK__
 
-     // There are a lot of hacks related to child frame menu bar handling in
 
-     // wxGTK and, in particular, the code in src/gtk/mdi.cpp relies on getting
 
-     // idle events to really put everything in place. Moreover, as wxGTK uses
 
-     // GtkNotebook as its MDI pages container, the frame must be shown for all
 
-     // this to work as gtk_notebook_set_current_page() doesn't do anything if
 
-     // called for a hidden window (this incredible fact cost me quite some time
 
-     // to find empirically -- only to notice its confirmation in GTK+
 
-     // documentation immediately afterwards). So just do whatever it takes to
 
-     // make things work "as usual".
 
-     child->Show();
 
-     parent->Show();
 
-     wxYield();
 
- #endif // __WXGTK__
 
-     TestEvtSink sinkDoc('d');
 
-     doc->Connect(wxEVT_MENU,
 
-                  wxEventHandler(TestEvtSink::Handle), NULL, &sinkDoc);
 
-     TestEvtSink sinkView('v');
 
-     view->Connect(wxEVT_MENU,
 
-                   wxEventHandler(TestEvtSink::Handle), NULL, &sinkView);
 
-     TestEvtSink sinkChild('c');
 
-     child->Connect(wxEVT_MENU,
 
-                    wxEventHandler(TestEvtSink::Handle), NULL, &sinkChild);
 
-     // Check that wxDocument, wxView, wxDocManager, child frame and the parent
 
-     // get the event in order.
 
-     ASSERT_MENU_EVENT_RESULT( menuChild, "advmcpA" );
 
- #if wxUSE_TOOLBAR
 
-     // Also check that toolbar events get forwarded to the active child.
 
-     wxToolBar* const tb = parent->CreateToolBar(wxTB_NOICONS);
 
-     tb->AddTool(wxID_APPLY, "Apply", wxNullBitmap);
 
-     tb->Realize();
 
-     // As in CheckMenuEvent(), use toolbar method actually sending the event
 
-     // instead of bothering with wxUIActionSimulator which would have been
 
-     // trickier.
 
-     g_str.clear();
 
-     tb->OnLeftClick(wxID_APPLY, true /* doesn't matter */);
 
-     CPPUNIT_ASSERT_EQUAL( "advmcpA", g_str );
 
- #endif // wxUSE_TOOLBAR
 
- }
 
- #if wxUSE_UIACTIONSIMULATOR
 
- class ContextMenuTestWindow : public wxWindow
 
- {
 
- public:
 
-     ContextMenuTestWindow(wxWindow *parent, char tag)
 
-         : wxWindow(parent, wxID_ANY),
 
-           m_tag(tag)
 
-     {
 
-         Connect(wxEVT_CONTEXT_MENU,
 
-                 wxContextMenuEventHandler(ContextMenuTestWindow::OnMenu));
 
-     }
 
- private:
 
-     void OnMenu(wxContextMenuEvent& event)
 
-     {
 
-         g_str += m_tag;
 
-         event.Skip();
 
-     }
 
-     const char m_tag;
 
-     wxDECLARE_NO_COPY_CLASS(ContextMenuTestWindow);
 
- };
 
- void EventPropagationTestCase::ContextMenuEvent()
 
- {
 
-     ContextMenuTestWindow * const
 
-         parent = new ContextMenuTestWindow(wxTheApp->GetTopWindow(), 'p');
 
-     wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
 
-     ContextMenuTestWindow * const
 
-         child = new ContextMenuTestWindow(parent, 'c');
 
-     parent->SetSize(100, 100);
 
-     child->SetSize(0, 0, 50, 50);
 
-     child->SetFocus();
 
-     wxUIActionSimulator sim;
 
-     const wxPoint origin = parent->ClientToScreen(wxPoint(0, 0));
 
-     // Right clicking in the child should generate an event for it and the
 
-     // parent.
 
-     g_str.clear();
 
-     sim.MouseMove(origin + wxPoint(10, 10));
 
-     sim.MouseClick(wxMOUSE_BTN_RIGHT);
 
-     // At least with MSW, for WM_CONTEXTMENU to be synthesized by the system
 
-     // from the right mouse click event, we must dispatch the mouse messages.
 
-     wxYield();
 
-     CPPUNIT_ASSERT_EQUAL( "cp", g_str );
 
-     // Right clicking outside the child should generate the event just in the
 
-     // parent.
 
-     g_str.clear();
 
-     sim.MouseMove(origin + wxPoint(60, 60));
 
-     sim.MouseClick(wxMOUSE_BTN_RIGHT);
 
-     wxYield();
 
-     CPPUNIT_ASSERT_EQUAL( "p", g_str );
 
- }
 
- #endif // wxUSE_UIACTIONSIMULATOR
 
 
  |